LeetCode刷题笔记1——数组

LeetCode刷题笔记1——数组

存在重复元素

题目

给定一个整数数组,判断是否存在重复元素。

如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false

示例

示例 1:

输入: [1,2,3,1]
输出: true

示例 2:

输入: [1,2,3,4]
输出: false

示例 3:

输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

代码

public class ContainsDuplicate {
	public boolean containsDuplicate(int[] nums) {
		Arrays.sort(nums);//解题关键点
		for(int i = 0;i<nums.length-1;i++) {
			if(nums[i]==nums[i+1]) {
				return true;
			}
		}
		return false;
	}
}

🏷️ 关键点还是排序

最大字数组和

题目

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4

代码

class Solution {
	public int maxSubArray(int[] nums) {
		int sum = -10000, temp = 0;
		for (int i = 0; i < nums.length; i++) {
			if (temp > 0)
				temp += nums[i];//大于0就加上去
			else
				temp = nums[i];//否则重新开始
			if (temp > sum)
				sum = temp;
		}
		return sum;
	}//动态规划问题
}

🏷️ 关键是动态规划

两数之和

题目

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

暴力求解

class Solution {
	public int[] twoSum(int[] nums, int target) {
		int[] result = new int[2];
		for (int i = 0; i < nums.length; i++) {
			for (int j = i + 1; j < nums.length; j++) {
				if (nums[i] + nums[j] == target) {
					result[0] = i;
					result[1] = j;
					return result;
				}
			}
		}
		return result;
	}
}

使用hashMap

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; ++i) {
            if (hashtable.containsKey(target - nums[i])) {
                return new int[]{hashtable.get(target - nums[i]), i};
            }
            hashtable.put(nums[i], i);//key:num[i] value:i
        }
        return new int[0];
    }
}

使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到O(1)。

这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。

合并两个有序数组

题目

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。

注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

提示:

nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-10^9 <= nums1[i], nums2[j] <= 10^9

直接合并后排序

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        for (int i = m; i < m+n; i++) {
            nums1[i]=nums2[i-m];
        }
        Arrays.sort(nums1);
    }
}

时间复杂度:O((m+n)log(m+n))
排序序列长度为 m+nm+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log(m+n))。

空间复杂度:O(log(m+n))。
排序序列长度为 m+nm+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n))。

双指针法

使用双指针方法。这一方法将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。如下面的动画所示:

gif1

class Solution {
    public static void merge(int[] nums1, int m, int[] nums2, int n) {
        int p1 = 0, p2 = 0;// 双指针
        int[] temp = new int[m + n];
        int element;
        while (p1 < m || p2 < n) {
            if (p1 == m) {
                element = nums2[p2++];
                // 第一个数组已经全部放入
            } else if (p2 == n) {
                element = nums1[p1++];
                // 第二个数组已经全部放入
            } else if (nums1[p1] < nums2[p2]) {
                element = nums1[p1++];
            } else {
                element = nums2[p2++];
            } // 选取较小的放入temp
            temp[p1 + p2 - 1] = element;
        }
        for (int i = 0; i < m + n; i++) {
            nums1[i] = temp[i];
        }
    }
}

两个数组的交集

题目

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000

使用Set

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new HashSet<>();
        for (int i : nums1)
            set1.add(i);//将nums1中的元素放入集合set1
        for (int i : nums2) {
            if (set1.contains(i)) {
                set2.add(i);
            }//将重复的元素放入set2
        }
        int[] result = new int[set2.size()];
        int j = 0;
        for (int i : set2) {
            result[j++] = i;
        }
        return result;
    }
}

两个数组的交集Ⅱ

题目

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

提示:

1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000

利用Hash表

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            return intersect(nums2, nums1);
        } // 从较短的数组开始遍历,以减少空间复杂度
        Map<Integer, Integer> record = new HashMap<>();
        for (int i : nums1) {
            int count = record.getOrDefault(i, 0) + 1;
            // getOrDefault: 寻找i的value值,若不存在则返回0
            record.put(i, count);
        }
        int[] result = new int[nums1.length];
        int index = 0;
        for (int i : nums2) {
            int count2 = record.getOrDefault(i, 0);
            if (count2 > 0) {
                result[index++] = i;
                count2--;
                if(count2>0){
                    record.put(i, count2);
                }else{
                    record.remove(i);
                }
            }
        }
        return Arrays.copyOfRange(result, 0, index);//复制数组
    }
}

首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数,然后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数。

fig1

题目来源

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/contains-duplicate/

链接:https://leetcode-cn.com/problems/maximum-subarray/

链接:https://leetcode-cn.com/problems/two-sum

链接:https://leetcode-cn.com/problems/merge-sorted-array

链接:https://leetcode-cn.com/problems/intersection-of-two-arrays/

链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

posted @   雨落俊泉  阅读(78)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示