数组的经典算法题
移动数组
//给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 //// 示例: //// 输入: [0,1,0,3,12]//输出: [1,3,12,0,0] //// 说明: //// // 必须在原数组上操作,不能拷贝额外的数组。 // 尽量减少操作次数。 // // Related Topics 数组 双指针//leetcode submit region begin(Prohibit modification and deletion)class Solution { public void moveZeroes(int[] nums) { //1 读懂题目要求: // 将数组中 0 移动到数组的末尾,同时保持非零元素的相对顺序 // 必须在原数组上操作,不能拷贝额外的数组 // 尽量减少操作次数 //2 解题思路: // 解法1: loop数组非0的当前loop count+1 一次从0开始替换不为0的元素,然后在loop 从count开始剩余的元素都是0// int count = 0;// for (int i = 0; i < nums.length; i++) {// if (nums[i] != 0) {// nums[count++] = nums[i];// }// }// for (int i = count; i <nums.length ; i++) {// nums[i] = 0;// } // 解法2: 上述使用了两个循环还可以在进行优化:通过类似的两个指针快慢指针,进行替换操作 for (int i = 0,count = 0; i < nums.length; i++) { if (nums[i] != 0){ //快慢指针进行元素替换操作// int temp = nums[i];// nums[i] = nums[count];// nums[count] = temp;// count++; //以上替换操作还可以在优化 可以将temp优化掉 if (count != i){ nums[count] = nums[i]; nums[i] = 0; } count++; } } }}//leetcode submit region end(Prohibit modification and deletion)
合并排序数组
//给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。 //// 初始化 A 和 B 的元素数量分别为 m 和 n。 //// 示例: //// 输入://A = [1,2,3,0,0,0], m = 3//B = [2,5,6], n = 3//1 2 3 2 5 6//输出: [1,2,2,3,5,6] // Related Topics 数组 双指针import java.util.Arrays;//leetcode submit region begin(Prohibit modification and deletion)class Solution { public void merge(int[] A, int m, int[] B, int n) {// solutionOne(A,m,B,n); } /** * 逆向双指针解法:双指针从m n的位置来时逆向查找 并添加到数组的尾部,注意 * 已经排好序的数组哪个大就会在最后,原地修改数组A 而不用在开一个额外的数组空间 * * @param A * @param m * @param B * @param n */ public void solutionS(int[] A, int m, int[] B, int n) { int pa = m - 1; int pb = n - 1; int t = m + n - 1; int cur = 0; while (pa >= 0 || pb >= 0) { if (pa == -1){ cur = B[pb--]; }else if (pb == -1){ cur = A[pa--]; }else if (A[pa] > B[pb]){ cur = A[pa--]; } else { cur = B[pb--]; } A[t--] = cur; } } /** * 双指针解法:注意题目描述的是A B 已经被排序利用这个性质来解答,注意双指针解法 * 在数组中必须是排好序的数组,既然A B 已经排好序了,那么一个指针指向A 的0下标pa=0, 一个 * 指针指向B的0 下标pb=0,判断A[pa] B[pb]的大小 小的那个放到一个新的数组中,如果pa==m||pb==n 则循环终止 * @param A * @param m * @param B * @param n */ public void solutionTwo(int[] A, int m, int[] B, int n){ int pa=0,pb=0; int[] result = new int[m+n]; int count = 0; int cur = 0; while (pa < m || pb < n){ if (pa == m){ cur = B[pb++]; }else if (pb == n){ cur = A[pa++]; }else if (A[pa] < B[pb]){ cur = A[pa++]; }else{ cur = B[pb++]; } result[count++] = cur; } for (int i = 0; i < result.length; i++) { A[i] = result[i]; } } /** * 暴力破解法: * 思路:既然题目要求要合并到A中,首先将B的数据合并到A中,然后在对A进行排序 * @param A * @param m * @param B * @param n */ public void solutionOne(int[] A, int m, int[] B, int n){ int num = m + n; //1 将B的数据添加到A中 1 2 3 2 5 6 直接从m开始向A中添加数据 //边界 //[0,0] //0 //[1] //1 //错误用例: //[4,0,0,0,0,0] //1 //[1,2,3,5,6] //5 for (int i = 0; i < n; i++) { A[m + i] = B[i]; } //2 排序A中的数据 通过快慢双指针进行 1 2 3 2 5 6 for (int i = 0; i < num - 1; i++) { for (int j = i + 1; j < num; j++) { if (A[i] > A[j]) { int temp = A[j]; A[j] = A[i]; A[i] = temp; } } } }}//leetcode submit region end(Prohibit modification and deletion)
两数之和
//给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 //// 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 //// 示例: //// 给定 nums = [2, 7, 11, 15], target = 9////因为 nums[0] + nums[1] = 2 + 7 = 9//所以返回 [0, 1]// // Related Topics 数组 哈希表//leetcode submit region begin(Prohibit modification and deletion)class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer,Integer> map = new HashMap<>();//记录所有数组值和下标 for(int i=0;i<nums.length;i++){ int result = target - nums[i]; if(map.containsKey(result) && map.get(result) != i){ return new int[]{map.get(result),i}; }else{ map.put(nums[i],i); } } return new int[]{}; }}//leetcode submit region end(Prohibit modification and deletion)
三数之和
//给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复//的三元组。 //// 注意:答案中不可以包含重复的三元组。 //// //// 示例: //// 给定数组 nums = [-1, 0, 1, 2, -1, -4],////满足要求的三元组集合为://[// [-1, 0, 1],// [-1, -1, 2]//]// // Related Topics 数组 双指针import java.util.ArrayList;import java.util.Arrays;import java.util.List;//leetcode submit region begin(Prohibit modification and deletion)class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> lists = new ArrayList<>(); if(nums == null || nums.length < 3) return lists; // 假设输入:[-1, 0, 1, 2, -1, -4] //先对数组进行排序 数组一般的解法使用双指针解法 要使用双指针解法就必须是排好序的数组 Arrays.sort(nums);//[-4,-1,-1,0,1,2] //数组最大的下标 int len = nums.length - 1; //判断边界值 if (nums[0] > 0 || nums[len] < 0) {//如果最小值大于0 那么不可能有相加等于0的,如果最大值<0 那么整个数组的值都是小于0 那么也不可能得到结果 return lists; } //[-4,-1,-1,0,1,2] // L R // i = L+1 for (int i = 0; i < nums.length - 2; i++) { //判断 num[i] 和 num[i+1]是否重复 if (i > 0 && nums[i] == nums[i - 1]) continue; int L = i + 1; int R = nums.length - 1; while (L < R) { int result = nums[L] + nums[R] + nums[i]; if (result < 0) { //如果得到的结果小于0则说明L要完右移动 增大值 同时要判断L是否重复 L++; } else if (result > 0) { //如果得到的结果大于0则说明R要往左移动 减小值 同时要判断R是否重复 R--; } else { lists.add(Arrays.asList(nums[i], nums[L], nums[R])); //==0 说明得到结果了 同时还得去重 while (L < R && nums[L] == nums[L + 1]) L++; L++; while (L < R && nums[R] == nums[R - 1]) R--; R--; } } } return lists; }}//leetcode submit region end(Prohibit modification and deletion)
数组算法解题思路