Leetcode刷题记录

数组

数组变换

#方法:根据规则,并用上递归调用。注意要额外复制一份数组

class Solution:
    def transformArray(self, arr: List[int]) -> List[int]:
        n = len(arr)


        arr_new = copy.copy(arr)
        for i in range(1,n-1):

            if (arr[i] < arr[i-1] and arr[i] < arr[i+1]) :
                arr_new[i] = arr_new[i] + 1
            elif  (arr[i] > arr[i-1] and arr[i] > arr[i+1]):
                arr_new[i] = arr_new[i] - 1
        if arr == arr_new:
            return arr_new
        else:
            return self.transformArray(arr_new)

打乱数组

class Solution:

    def __init__(self, nums: List[int]):
        self.array = nums
        self.original = list(nums)


    def reset(self) -> List[int]:
        """
        Resets the array to its original configuration and return it.
        """
        self.array = list(self.original)
        return self.array

    def shuffle(self) -> List[int]:
        """
        Returns a random shuffling of the array.
        """
        random.shuffle(self.array)
        return self.array
#方法一:
def shuffle(self):
        aux = list(self.array)

        for idx in range(len(self.array)):
            remove_idx = random.randrange(len(aux))
            self.array[idx] = aux.pop(remove_idx)

        return self.array

# 方法二
def shuffle(self):
        for i in range(len(self.array)):
            swap_idx = random.randrange(i, len(self.array))
            self.array[i], self.array[swap_idx] = self.array[swap_idx], self.array[i]
        return self.array

旋转数组

# 方法一:逐个插入
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        for i in range(k):
            nums.insert(0,nums.pop())
            
# 方法二: 数组切片
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        l = len(nums)
        k = k % l
        nums[:] = nums[l-k:] + nums[:l-k]
        
# 方法三:三次翻转
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        l = len(nums)
        k = k%l
        self.reverse(nums,0,l-1)
        self.reverse(nums,0,k-1)
        self.reverse(nums,k,l-1)

    def reverse(self,nums,start,end):
        while start < end:
            nums[start],nums[end] = nums[end],nums[start]
            start += 1
            end -= 1

三数之和——双指针

def threesum(nums,target):
        nums = sorted(nums)
        n = len(nums)
        result = []
        if n < 3:
            return []
    
        for i in range(n):
            L = i + 1
            R = n - 1
            if i > 0 and nums[i] == nums[i-1] :
                continue
            while(L<R):
                if nums[i] + nums[L] +nums[R] == target:
                    result.append([nums[i],nums[L],nums[R]])
                    while L < R and nums[L] == nums[L+1]:
                        L = L + 1
                    while L < R and nums[R] == nums[R-1]:
                        R = R  - 1
                    L = L + 1
                    R = R - 1
                elif nums[i] + nums[L] +nums[R] > target:
                    R = R - 1
                else:
                    L = L + 1 

        return result

最接近的三数之和——双指针

def close_threesum(nums,target):
        n = len(nums)
        nums = sorted(nums)
        result = nums[0] + nums[1] + nums[2]
        for i in range(n):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            L = i + 1
            R = n - 1              
            while L < R:
                ans = nums[i] + nums[L] + nums[R]
                print(L,R,ans)
                if ans == target:
                    return ans
                if abs(result-target) > abs(ans- target):
                    result = ans 
                if ans > target:
                    R = R - 1
                else:
                    L = L + 1
            print('epoch = --------------',i,result)
        return result

较小的三数之和——双指针

def small_threesum(nums,target):
        n = len(nums)
        nums = sorted(nums)
        result = 0
        for i in range(n):
            L = i + 1
            R = n - 1

            while L < R:
                while L < R and nums[i] + nums[L] + nums[R] >= target:
                    R = R - 1
                if nums[i] + nums[L] + nums[R] < target:
                    result = result + R - L
                L = L + 1

        return result  

两个有序数组的中位数

def findMedianSortedArrays(nums1, nums2):
        m = len(nums1)
        n = len(nums2)
        if m > n:
            nums1,nums2,m,n = nums2,nums1,n,m
        if n == 0:
            return ValueError

        imin,imax,half = 0, m, (m+n+1)//2

        while imin <= imax:
            i = (imin + imax) // 2
            j = half - i
            if i < m and nums1[i] < nums2[j-1]:
                imin = imin + 1
            elif i > 0 and nums1[i-1] > nums2[j]:
                imax = imax - 1
            else:

                if i == 0: max_left = nums2[j-1]
                elif j == 0 :max_left = nums1[i-1]
                else: max_left = max(nums1[i-1],nums2[j-1])

                if i == m:min_right = nums2[j]
                elif j==n:min_right = nums1[i]
                else: min_right = min(nums1[i],nums2[j])
                    
                
                if (m+n)% 2 == 1:
                    return max_left
                
                return (max_left+min_right) / 2.0            

4.19更新

46. 全排列

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

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def sort(nums,k):
            n = len(nums[0])
            ans = []
            for lis in nums:
                for i in range(k,n):
                    c_lis = lis.copy()
                    c_lis[k],c_lis[i] = c_lis[i],c_lis[k]
                    ans.append(c_lis)
            return ans
        
        num = [nums]
        for k in range(len(nums)):
            num = sort(num,k)
        return num

个人做法,即0位置与1到n-1位置交换,1位置与2到n-1位置交换。。。。
能解,但是会用到额外的空间;而且与回溯法类似?

看看一行python的解法

def permute(self, nums: List[int]) -> List[List[int]]:
        return list(itertools.permutations(nums))

以及回溯算法的解法

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res = []
        def backtrack(nums, tmp):
            if not nums:
                res.append(tmp)
                return 
            for i in range(len(nums)):
                backtrack(nums[:i] + nums[i+1:], tmp + [nums[i]])
        backtrack(nums, [])
        return res

这里回溯体现在什么地方呢,就是每次res.append()之后,return这个地方,总之应该会有清空tmp的作用吧?还没尝试。


字符串相关

字母大小写全排列

给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。

class Solution:
    '''
    def letterCasePermutation(self, S: str) -> List[str]:
        f = lambda x: (x.lower(), x.upper()) if x.isalpha() else x
        return map("".join, itertools.product(*map(f, S)))
    '''

    def letterCasePermutation(self, S: str) -> List[str]:
        ans = [[]]

        for char in S:
            n = len(ans)
            if char.isalpha():
                for i in range(n):
                    ans.append(ans[i][:])
                    ans[i].append(char.lower())
                    ans[n+i].append(char.upper())
            else:
                for i in range(n):
                    ans[i].append(char)

        return map("".join, ans)

两个办法,一个是看成笛卡尔积,也就是从所有集合中选择每种可能的组合。
另一个是递归法,这里要学习的写法是

 for i in range(n):
 	ans.append(ans[i][:])

字符串相加

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        i,j = len(num1)-1,len(num2)-1
        head = 0
        res = ''
        while i >= 0 or j >= 0:
            add1 = int(num1[i]) if i >= 0 else 0
            add2 = int(num2[j])  if j >= 0 else 0
            sum_ = add1 + add2 + head
            head = sum_ // 10
            res = str(sum_ % 10) + res 
            i -=1
            j -= 1
        return '1' + res if head != 0 else res

两个指针,从尾往头扫,相加。

1071. 字符串的最大公因子

对于字符串 S 和 T,只有在 S = T + … + T(T 与自身连接 1 次或多次)时,我们才认定 “T 能除尽 S”。
返回最长字符串 X,要求满足 X 能除尽 str1 且 X 能除尽 str2。

class Solution:
    def gcdOfStrings(self, str1: str, str2: str) -> str:
        if str1 == str2:
            return str1
        str0 = str1 if len(str1)< len(str2) else str2         ##枚举法来解决
        n =len(str0)
        for i in range(n,0,-1):
            ans = str0[:i]
            if len(str1) % len(ans) == 0 and len(str2) % len(ans) == 0:
                l1 = len(str1) // len(ans)
                l2 = len(str2) // len(ans)
                if str1 == l1 * ans and str2 == l2 *ans:
                    return ans
        
        return ''

这里用的是暴力的枚举法,由于是最大公因子,所以就从后往前慢慢缩小,找到能整除的子串

443. 压缩字符串、

给定一组字符,使用原地算法将其压缩。

压缩后的长度必须始终小于或等于原数组长度。

数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。

在完成原地修改输入数组后,返回数组的新长度。

class Solution:
    def compress(self, chars: List[str]) -> int:
        n = len(chars)
        pos = 0
        cnt = 1
        if len(chars) == 1:
            return len(chars)

        for i,value in enumerate(chars):
            if i < n-1  and  chars[i + 1] == value :
                cnt = cnt + 1
            else:
                chars[pos] = value
                pos = pos + 1
                if cnt != 1:
                    for j in str(cnt):
                        chars[pos] = j
                        pos = pos + 1
                cnt = 1
        for i in range(pos,n):
            chars.pop(-1)

        return len(chars)

一个指针记录位置,一个计数器统计次数。
遍历,后一位与当前相同,计数器计数。
不同,则记录下当前值,指针进一位,开始记录计数器的数字。
最后把多余的清除

758. 字符串中的加粗单词

给定一个关键词集合 words 和一个字符串 S,将所有 S 中出现的关键词加粗。所有在标签 中的字母都会加粗。

返回的字符串需要使用尽可能少的标签,当然标签应形成有效的组合。

例如,给定 words = [“ab”, “bc”] 和 S = “aabcd”,需要返回 “aabcd”。注意返回 “aabcd” 会使用更多的标签,因此是错误的。

import re
class Solution:
    def boldWords(self, words: List[str], S: str) -> str:
        idx = []
        for word in words:
            loc = S.find(word)
            while loc != -1:
                idx.append([loc, loc + len(word)])
                loc = S.find(word, loc + 1)

        idx = sorted(idx)

        res = self.merge(idx)
        lis = list(S)
        i = 0
        for pos in res:
            lis.insert(pos[0]+i,'<b>')
            i += 1
            lis.insert(pos[1]+i, '</b>')
            i += 1
        result = ''.join(lis)
        return result
        
    def merge( self,intervals):

        if len(intervals) == 0:
            return []
        
        res = []
        intervals = list(sorted(intervals))
        
        low = intervals[0][0]
        high = intervals[0][1]
        
        for i in range(1,len(intervals)):
            if high >= intervals[i][0]:
                if high < intervals[i][1]:
                    high = intervals[i][1]
            else:
                res.append([low,high])
                low = intervals[i][0]
                high = intervals[i][1]
                
        res.append([low,high])
        return res

两部分:
找到单词所在位置,区间的形式;
这部分一开始用正则表达,但对于ee与eee这种情况,正则表达式我不知道该如何解决;
上面的写法是参照别人的。string.find(),如果超过当前位置,则会返回-1

合并区间,根据区间位置插入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值