leetcode刷题Task4 8.26(9-代码敲不队-QQ)

1.两数之和
给定一个整数数组nums和一个目标值target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:
给定
nums = [2, 7, 11, 15], target = 9
因为
nums[0] + nums[1] = 2 + 7 = 9
所以返回[0, 1]

解法一:
将数组排序,之后设置两个高低指针,从两端遍历,若所指数之和小于target,则低指针加一,若大于则高指针减一,等于则返回。

class Solution:
    def twoSum(self, nums: list, target: int) -> list:
        nums.sort()
        i,j=0,len(nums)-1
        while i<j:
            if nums[i]+nums[j]==target:
                return [i,j]
            elif nums[i]+nums[j]<target:
                i+=1
            else:
                j-=1
            return []
a=Solution()
print(a.twoSum([1,1,2,3,3,4,4,8],16))

解法二:
暴力求解,两层循环:

class Solution:
    def twoSum(self, nums: list, target: int) -> list:
            n = len(nums)
            for x in range(n):
                for y in range(x + 1, n): #x之前的已经试过了,所以从x+1开始
                    if nums[x] + nums[y] == target:
                        return x, y
a=Solution()
print(a.twoSum([1,1,2,2,3,3,4,4,8,8],3))

解法三:使用字典映射,键为数组元素,值为数组元素的下标:

class Solution:
    def twoSum(self, nums: list, target: int) -> list:
        d={
    
    }
        for i in range(len(nums)):
            if target-nums[i] in d:
                return [i,d[target-nums[i]]]
            else:
                d[nums[i]]=i
        return []
a=Solution()
print(a.twoSum([1,1,3,2,2],6))
  1. 三数之和
    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
    注意:答案中不可以包含重复的三元组。

示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

解法一:三数之和为0,则至少有一个数必然小于等于0,根据此性质,将数组排序,则第一个数应存在于小于等于0的范围,第二个数和第三个数在第一个数之后的范围里寻找,即化为了两数之和的问题,使用高低指针法解决即可:

class Solution:
    def threeSum(self, nums: list) -> list:
        nums.sort()
        li=[]
        for i in range(len(nums)):
                if nums[i]>0:
                    return li
                if i>0 and nums[i]==nums[i-1]:
                    continue
                target=-nums[i]
                j,k=i+1,len(nums)-1
                while j<k:
                    if nums[j] + nums[k] == target:
                        a=[nums[i],nums[j],nums[k]]
                        a.sort()
                        if a not in li:
                            li.append(a)
                        k-=1
                    elif nums[j] + nums[k] < target:
                        j += 1
                    else:
                        k -= 1
        return li
a=Solution()
print(a.threeSum([0,0,0]))
  1. 最接近的三数之和
    给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案
    示例:
    输入:nums = [-1,2,1,-4], target = 1
    输出:2
    解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4

解法一:
此题将三数之和为0改为三数之和最接近某数,令后两数之和等于target减去第一个数即可回到三数之和的套路,定义一个ans来记录最接近target的值,
然后依然使用高低指针法查找,每次产生的的三数之和都要判断看是否需要更新,注意判断更新的条件写法以及高低指针移动时跳过相同值:

class Solution:
    def threeSumClosest(self, nums: list,target:int):
        nums.sort()
        n = len(nums)
        ans = 10**10
        for i in range(n):
                if i>0 and nums[i]==nums[i-1]:
                    continue
                j,k=i+1,n-1
                while j<k:
                    s=nums[i] + nums[j] + nums[k]
                    if abs(s - target) < abs(ans - target):
                        ans = s
                    if s==target:
                        return target
                    elif s<target:
                        j1= j+1
                        while j1<k and nums[j1]==nums[j]:
                            j1+=1
                        j=j1
                    else:
                        k1 = k - 1
                        while k1 >j and nums[k1] == nums[k]:
                            k1 += 1
                        k = k1
        return ans
a=Solution()
print(a.threeSumClosest([-1,2,1,-4],1))
#2
  1. 四数之和
    给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
    注意:
    答案中不可以包含重复的四元组。
    示例:
    给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
    满足要求的四元组集合为:
    [
    [-1, 0, 0, 1],
    [-2, -1, 1, 2],
    [-2, 0, 0, 2]
    ]
    解法一:
    此题需要多加一层循环,选定第一个数后,第二个数从第一个数的后一个数开始,就转化为了三数之和问题,注意每一层循环里最开始跳过重复值的细节
class Solution:
    def threeSumClosest(self, nums: list,target:int):
        nums.sort()
        li = []
        n=len(nums)
        for x  in range(n):
            if x > 0 and nums[x] == nums[x - 1]:
                continue
            for i in range(x+1,n):
                if i > x+1 and nums[i] == nums[i - 1]: #多个相同值的第一个是不可以跳过的
                    continue
                j, k = i + 1, len(nums) - 1
                while j < k:
                    s=nums[x] +nums[i] +nums[j] + nums[k]
                    if s == target:
                        a = [nums[x],nums[i], nums[j], nums[k]]
                        if a not in li:
                            li.append(a)
                        while j < k and nums[j] == nums[j + 1]:
                            j += 1
                        while j < k and nums[k] == nums[k - 1]:
                            k -= 1
                        k -= 1
                        j += 1
                    elif s < target:
                        j += 1
                    else:
                        k -= 1
        return li
a=Solution()
print(a.threeSumClosest([1, 0, -1, 0, -2, 2],0))
#[[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]
  1. 字母异位词分组
    给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
    示例:
    输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
    输出:
    [
    [“ate”,“eat”,“tea”],
    [“nat”,“tan”],
    [“bat”]
    ]
    说明:
    所有输入均为小写字母。
    不考虑答案输出的顺序。

方法一:排序法
使用collections.defaultdict来初始化一个字典,然后将每一个字符串都排序然后转化成元组,作为键写入字典,字典的值最开始是一些空列表,用来记录字符组成与键相同的字符串:

import collections
class Solution:
    def groupAnagrams(self, strs:list):
        dic1 = collections.defaultdict(list)
        for i in strs:
            a=tuple(sorted(i))
            dic1[a].append(i)
        return dic1.values()
a=Solution()
print(a.groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))

方法二:计数法
还是创建一个字典,键为一个记录字母出现次数的元组,值还是记录字符串的列表:

import collections
class Solution:
    def groupAnagrams(self, strs:list):
        dic1 = collections.defaultdict(list)
        for s in strs:
            count = [0] * 26
            for c in s:
                count[ord(c) - ord('a')] += 1
            dic1[tuple(count)].append(s)
        return dic1.values()
a=Solution()
print(a.groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))
  1. 直线上最多的点数
    给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
    示例 1:
    输入: [[1,1],[2,2],[3,3]]
    输出: 3
    解释:
    ^
    |
    | o
    | o
    | o
    ±------------>
    0 1 2 3 4
    示例 2:
    输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
    输出: 4
    解释:
    ^
    |
    | o
    | o o
    | o
    | o o
    ±------------------>
    0 1 2 3 4 5 6

解法一:使用求最大公约数的方法求斜率,化简为int/int最简形式,这样不存在精度问题,创建一个字典,以化简后的斜率为键,统计经过一个点的所有直线中哪个直线上点最多,依次遍历所有点,即可找出直线上最多的点:

class Solution:
    def maxPoints(self, points: list) -> int:
        from collections import Counter, defaultdict
        # 所有点统计
        points_dict = Counter(tuple(point) for point in points)
        print(points_dict)
        # 把唯一点列举出来
        not_repeat_points = list(points_dict.keys())
        n = len(not_repeat_points)
        if n == 1: return points_dict[not_repeat_points[0]]
        res = 0
        # 求最大公约数
        def gcd(x, y):
            if y == 0:
                return x
            else:
                return gcd(y, x % y)

        for i in range(n - 1):
            # 点1
            x1, y1 = not_repeat_points[i][0], not_repeat_points[i][1]
            # 斜率
            slope = defaultdict(int)
            for j in range(i + 1, n):
                # 点2
                x2, y2 = not_repeat_points[j][0], not_repeat_points[j][1]
                dy, dx = y2 - y1, x2 - x1
                # 方式一 利用公约数
                g = gcd(dy, dx)
                if g != 0:
                    dy //= g
                    dx //= g
                slope["{}/{}".format(dy, dx)] += points_dict[not_repeat_points[j]]
            res = max(res, max(slope.values()) + points_dict[not_repeat_points[i]])
        return res
a=Solution()
print(a.maxPoints([[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]))

存在重复元素
给定一个整数数组和一个整数k,判断数组中是否存在两个不同的索引i和j,使得nums[i] = nums[j],并且i和j的差的绝对值至多为k。
示例1:
输入: nums = [1, 2, 3, 1], k = 3
输出: true
示例2:
输入: nums = [1, 0, 1, 1], k = 1
输出: true
示例
3:输入: nums = [1, 2, 3, 1, 2, 3], k = 2
输出: false
解法一:暴力解法,用一个指针i遍历数组,检查在i+1到i+k+1的范围内所有值看是否与i相同:

class Solution:
    def containsNearbyDuplicate(self, nums: list, k: int) -> bool:
       for i in range(len(nums)):
           for j in range(i+1,min(i+k+1,len(nums))):
               if nums[i]==nums[j]:
                   return True
       return False
a=Solution()
print(a.containsNearbyDuplicate([1,2,3,1],3))#True
print(a.containsNearbyDuplicate([1,0,1,1],1))#True
print(a.containsNearbyDuplicate([1,2,3,1,2,3],2))#False

解法二:建立一个字典,遍历nums中的元素,如果nums[i]在字典中并且下标与i的距离小于等于k,则返回true:

class Solution:
    def containsNearbyDuplicate(self, nums: list, k: int) -> bool:
        dict = {
    
    }
        for i in range(len(nums)):
            if nums[i] in dict and i - dict[nums[i]] <= k:
                return True
            dict[nums[i]] = i
        return False

存在重复元素
在整数数组nums中,是否存在两个下标i和j,使得nums[i]和nums[j]的差的绝对值小于等于t ,且满足i和j的差的绝对值也小于等于ķ 。
如果存在则返回true,不存在返回false。
示例1:
输入: nums = [1, 2, 3, 1], k = 3, t = 0
输出: true
示例2:
输入: nums = [1, 0, 1, 1], k = 1, t = 2
输出: true
示例3:
输入: nums = [1, 5, 9, 1, 5, 9], k = 2, t = 3
输出: false

解法一:遍历I,在I后的k个数里寻找符合条件的数

class Solution:
    def containsNearbyAlmostDuplicate(self, nums: list, k: int,t: int) -> bool:

        n=len(nums)

        for i in range(n):
            for j in range(i+1,min(i+k+1,n)):
                if abs(nums[i]-nums[j])<=t:
                    return True
        return False
a=Solution()
print(a.containsNearbyAlmostDuplicate([1,2,3,1],3,0))
print(a.containsNearbyAlmostDuplicate([1,0,1,1],1,2))
print(a.containsNearbyAlmostDuplicate([1,5,9,1,5,9],2,3))

方法二:

class Solution:
    def containsNearbyAlmostDuplicate(self, nums: list, k: int,t: int) -> bool:
        if t < 0 or not k or not nums:
            return False

        if k == 1:
            for i in range(len(nums) - 1):
                if abs(nums[i] - nums[i + 1]) <= t:
                    return True
            return False

        if not t:
            dct = {
    
    }
            for inx, i in enumerate(nums):
                if i in dct:
                    if inx - dct[i] <= k:
                        return True
                dct[i] = inx
            return False

        lst = []
        i = nums[0]
        lst.append(sum([(i - j, i + j) for j in range(t + 1)], ()))

        for i in nums[1:]:
            if i in set(sum(lst, ())):
                return True
            lst.append(sum([(i - j, i + j) for j in range(t + 1)], ()))
            lst = lst[-k:]

        return False
a=Solution()
print(a.containsNearbyAlmostDuplicate([1,2,3,1],3,0))
print(a.containsNearbyAlmostDuplicate([1,0,1,1],1,2))
print(a.containsNearbyAlmostDuplicate([1,5,9,1,5,9],2,3))
  1. 回旋镖的数量
    给定平面上 n 对不同的点,“回旋镖” 是由点表示的元组 (i, j, k) ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺序)。
    找到所有回旋镖的数量。你可以假设 n 最大为 500,所有点的坐标在闭区间 [-10000, 10000] 中。
    示例:
    输入:
    [[0,0],[1,0],[2,0]]
    输出:
    2
    解释:
    两个回旋镖为 [[1,0],[0,0],[2,0]] 和 [[1,0],[2,0],[0,0]]
    解法一:每次固定一个点,使用哈希表存储其他点到这个点的距离,如果存在记录次数,回旋镖的数量应为次数*(次数-1):
class Solution:
    def numberOfBoomerangs(self, points: list[list]) -> int:
        res=0
        for i in points:
            dicts={
    
    }
            for j in points:
                if i==j:
                    continue
                dicts[(i[0]-j[0])**2+(i[1]-j[1])**2]=dicts.get((i[0]-j[0])**2+(i[1]-j[1])**2,0)+1
            for i in dicts.values():
                res+=i*(i-1)
        return res
  1. 四数相加 II
    给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
    为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。
    例如:
    输入:
    A = [ 1, 2]
    B = [-2,-1]
    C = [-1, 2]
    D = [ 0, 2]
    输出:
    2
    解释:
    两个元组如下:
  2. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
  3. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

解法一:
初始化计数器 dic,dic 记录数组 A 和 B 元素的和,及其次数
遍历数组 C 和 D,累加满足四数相加和为 0 的个数:

class Solution:
    def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:
        dic = collections.Counter()
        ans = 0
        for a in A:
            for b in B:
                dic[a+b] += 1
        for c in C:
            for d in D:
                ans += dic[-c-d]
        return ans

猜你喜欢

转载自blog.csdn.net/m0_45672993/article/details/108234499