编程之法之字符串

字符串

1.1 字符串的旋转

(leetcode 796) 给定两个字符串, A 和 B。A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = 'abcde',在移动一次之后结果就是'bcdea' 。如果在若干次旋转操作之后,A 能变成B,那么返回True。
:主要需要考虑为空的情况,另外就是当num超过字符串长度

class Solution:
    def rotateString(self, A: str, B: str) -> bool:
        if not A and not B:
            return True
        if not A or not B:
            return False
        for i in range(len(A)+1):
            if B == self.rotate(A,i):
                return True
        return False
    
    def rotate(self,A,num):
        indx = num%len(A)
        return A[indx:] + A[:indx]

1.2 字符串的包含

给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短。请问,如何最快地判断字符串B中所有字母是否都在字符串A里?

def StringContain(strA,strB):
    strHash = 0
    for v in strA:
        strHash |= (1<<(ord(v)-ord('A'))
    for v in strB:
        if (strHash & (1 << (ord(v)-ord('A')))==0):
            return False
    return True

1.3 字符串的全排列

(leetcode 46) 给定一个没有重复数字的序列,返回其所有可能的全排列。

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        self.visited = [0] * len(nums)
        self.nums = nums
        self.result = []
        self.dfs([])
        return self.result
        
    def dfs(self,path):
        if len(path) == len(self.nums):
            self.result.append(path)
        else:
            for i in range(len(self.nums)):
                if not self.visited[i]:
                    self.visited[i] = 1
                    self.dfs(path+[self.nums[i]])
                    self.visited[i] = 0

第二种方法比第一种要慢

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        self.result = []
        self.perm(nums,0,len(nums))
        return self.result

    def perm(self,nums,fr,to):
        if to <= 1:
            self.result.append(nums)
            return
        if fr==to:
            tmp = nums[:]
            self.result.append(tmp)
        else:
            for i in range(fr,to):
                nums[i],nums[fr] = nums[fr],nums[i]
                self.perm(nums,fr+1,to)
                nums[i],nums[fr] = nums[fr],nums[i]                

1.3.1 字典序排列

(leetcode 31) 下一个排列。
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
注:这道题就是典型的字典序排列问题,过程如下:

  • 找到排列中最右边的一个升序首位位置i
  • 如果i小于0,说明找不到,则直接返回;
  • 找到排列中第i个位置右边最后一个比nums[i]大的位置j;
  • 交换i和j位置的数;
  • 把第i+1到最后的部分翻转;
class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # 找到最后一个升序首位
        indx = -1
        for i in range(len(nums)-2,-1,-1):
            if nums[i] < nums[i+1]:
                indx = i
                break
        # 已经找到所有的
        if indx<0:
            nums.sort()
            return
        # 找到右边最后一个比nums_i大的位置
        k = len(nums)-1
        for k in range(len(nums)-1,indx,-1):
            if nums[k] > nums[indx]:
                break
        nums[indx], nums[k] = nums[k], nums[indx]
        nums[indx+1:] = nums[indx+1:][::-1]

1.4 回文判断

(leetcode 234) 请判断一个链表是否为回文链表。
这道题比较经典,涉及到如何使用快慢表,如何翻转链表;

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        new_head = None
        while slow:
            p = slow
            slow = slow.next
            p.next = new_head
            new_head = p
        while new_head:
            if new_head.val != head.val:
                return False
            new_head = new_head.next
            head = head.next
        return True

1.5 最长回文子串

(leetcode 5) 最长回文子串
注:注意对情况的讨论,第一种解法参考编程之法,原文中的代码在while语句中缺少边界判断,会报错。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        if not s:
            return s
        s = "#".join(s.strip())
        s = "#" + s + "#"
        p = [0]*len(s)
        mx = 0
        for i in range(1,len(s)):
            if mx > i:
                p[i] = min(p[2*id-i],mx-i)
            else:
                p[i] = 1
            while i+p[i] < len(s) and i-p[i] > 0 and (s[i+p[i]] == s[i-p[i]]):
                p[i] += 1
            if p[i] + i > mx:
                mx = p[i] + i
                id = i
        l = max(p)-1
        indx = p.index(l+1)
        maxs = s[indx-l:indx+l+1]
        return "".join(maxs.split("#"))
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        maxl = 0
        start = 0
        for i in range(n):
            if i-maxl >= 1 and s[i-maxl-1:i+1] == s[i-maxl-1:i+1][::-1]:
                start = i - maxl - 1
                maxl += 2
                continue
            if i-maxl >= 0 and s[i-maxl:i+1] == s[i-maxl:i+1][::-1]:
                start = i - maxl
                maxl += 1
        return s[start:start+maxl]
posted @ 2019-07-17 00:11  静_渊  阅读(266)  评论(0编辑  收藏  举报