Leetcode刷题01-数组

数组

前言:为了巩固自己的python基础,这里每一个最优解法我都用使用python和java来编写。

数组的存储

数组的存储:c为每个元素占用的存储空间字节数

一维数组a[n]:Loc(a[i]) = Loc(a[0]) + i * c

二维数组a[m, n]:Loc(a[i, j]) = Loc(a[0, 0]) + (i * n + j) * c

三维数组a[m, n, l]:Loc(a[i, j, k]) = Loc(a[0, 0, 0]) + (i * n * l + j * l + k) * c

题目解析

两数之和

1.题目描述

在这里插入图片描述

2.解题思路及代码

  • 朴素做法:O(n^2)

双重for循环,直接判断两个下标的和是否等于target,等于直接输出结果。

	public int[] twoSum(int[] nums, int target) {
        for (int i = 0; i < nums.length; i ++ ) {
            for (int j = i + 1; j < nums.length; j ++ ) {
                if (nums[i] + nums[j] == target)    return new int[]{i, j};
            }
        }
        return new int[]{0, 0};
    }
  • 使用哈希表:O(n)

使用HashMap将数据存放到哈希表中,遍历每个元素,查找哈希表中是否包含target - x,如果包含直接返回结果,不包含继续遍历。

	public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        
        for (int i = 0; i < nums.length; i ++ ) {
            if (map.containsKey(target - nums[i]))
                return new int[] {map.get(target - nums[i]), i};
            map.put(nums[i], i);
        }
        return new int[0];
    }
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        map = dict()
        for i, num in enumerate(nums):
            if target - num in map:
                return [map[target - num], i]
            map[num] = i
        return []

最接近的三数之和

1.题目描述

在这里插入图片描述

2.解题思路及代码

  • 朴素做法:O(n^3)

三重循环,枚举三个数,判断他们的和与target的绝对值,返回绝对值最小的和

	public int threeSumClosest(int[] nums, int target) {
        int res = 0, subtract = Integer.MAX_VALUE;
        for (int i = 0; i < nums.length; i ++ ) {
            for (int j = i + 1; j < nums.length; j ++ ) {
                for (int k = j + 1; k < nums.length; k ++ ) {
                    int tmp = nums[i] + nums[j] + nums[k];
                    if (Math.abs(tmp - target) < subtract) {
                        subtract = Math.abs(tmp - target);
                        res = tmp;
                    }
                }
            }
        }
        return res;
    }
  • 排序+双指针:O(n^2)

对数组排序,枚举第一个元素,然后使用双指针枚举第二个和第三个元素,最后返回结果。

	public int threeSumClosest(int[] nums, int target) {        
        Arrays.sort(nums);
        int best = nums[0] + nums[1] + nums[2];
        
        for (int i = 0; i < nums.length - 2; i ++ ) { 
            int st = i + 1, ed = nums.length - 1;
            
            while(st < ed) {
                int sum = nums[i] + nums[st] + nums[ed];
                
                if (Math.abs(sum - target) < Math.abs(best - target)) {
                    best = sum;
                }
                
                if (sum < target)   st ++ ;
                else if (sum > target)  ed --;
                else    return best;
            }
        }
        return best;
    }
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        best = nums[0] + nums[1] + nums[2]
        
        for i in range(len(nums)):
            st = i + 1
            ed = len(nums) - 1
            while st < ed:
                s = nums[i] + nums[st] + nums[ed]
                if (abs(s - target) < abs(best - target)):
                    best = s
                if (s < target):
                    st += 1 
                elif s > target:
                    ed -= 1
                else:
                    return target
        
        return best

移除元素

1.题目描述

在这里插入图片描述

2.解题思路及代码

  • 快慢指针:O(n)

使用left表示最后数组的长度,right判断数组的元素是否等于val,不等于val就放入left指向的数组中。

	public int removeElement(int[] nums, int val) {
        int l = 0, r = 0;
        while(r < nums.length) {
            if (nums[r] != val) {
                nums[l ++ ] = nums[r];
            }
            r ++ ;
        }
        return l;
    }
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        l = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[l] = nums[i]
                l += 1
        return l

删除有序数组中的重复项

1.题目描述

在这里插入图片描述

2.解题思路及代码

  • 快慢指针:O(n)

使用left指向数组最左边,判断left和right是否相等,不相等则将right放入left后面的元素中,最后返回left+1,注意当nums数组为0时需要特判。

	public int removeDuplicates(int[] nums) {
        if (nums.length == 0)   return 0;
        int l = 0;
        for (int i = 1; i < nums.length; i ++ ) {
            if (nums[i] != nums[l]) {
                l ++ ;
                nums[l] = nums[i];
            }
        }
        return l + 1;
    }

另一种做法:判断right和right-1的元素是否相等,不相等则放入left中,然后left++

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        l = 0
        for i in range(len(nums)):
            if i == 0 or nums[i] != nums[i - 1]:
                nums[l] = nums[i]
                l += 1
        return l

三数之和

1.题目描述

在这里插入图片描述

2.解题思路及代码

本题是需要获取具体的数组元素,而不是数组下标,因此使用哈希表获取结果比较困难。这里首先对数组进行排序,然后确定第一个元素,然后确定第二个元素,第三个元素默认从最后一个元素获取,然后判断结果和0的差距,如果大,则回退。

同时需要注意,因为需要保证元素相同的算是同一个结果,因此如果第一个元素循环的时候如果和前一个元素相同,则不需要进行循环,第二个元素也需要同样的判断。只要保证第一个元素和第二个元素不重复,那么最后的结果一定是不重复的。

	public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        
        for (int i = 0; i < nums.length; i ++ ) {
            // 保证第一个元素不是重复的
            if (i > 0 && nums[i] == nums[i - 1])    continue;
            int k = nums.length - 1;
            for (int j = i + 1; j < nums.length; j ++ ) {
                // 保证第二个元素不是重复的
                if (j > i + 1 && nums[j] == nums[j - 1])    continue;
                while (nums[j] + nums[k] + nums[i] > 0 && j < k) k -- ;
                if (k == j) break;
                if (nums[j] + nums[k] + nums[i] == 0) {
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(nums[i]);
                    list.add(nums[j]);
                    list.add(nums[k]);
                    ans.add(list);
                }
            }
        }
        
        return ans;
    }
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n = len(nums)
        nums.sort()
        ans = list()
        
        for i in range(n):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            k = n - 1
            for j in range(i + 1, n):
                if j > i + 1 and nums[j] == nums[j - 1]:
                    continue
                while j < k and nums[j] + nums[k] + nums[i] > 0:
                    k -= 1
                if j == k:
                    break
                if nums[k] + nums[j] + nums[i] == 0:
                    ans.append([nums[i], nums[j], nums[k]])
        
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值