个人记录-LeetCode 15. 3Sum
来源:互联网 发布:mmd r18动作数据 编辑:程序博客网 时间:2024/05/16 07:01
问题:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: The solution set must not contain duplicate triplets.
For example, given array S = [-1, 0, 1, 2, -1, -4],A solution set is:[ [-1, 0, 1], [-1, -1, 2]]
题目的要求是:
从给定的数组中找到不重复的组合。
每个组合包含3个元素,其和为0。
代码示例:
1、暴力解法
public class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> result = new ArrayList<>(); if (nums == null || nums.length < 3 ) { return result; } int len = nums.length; //现将给定数组从小到大排序 Arrays.sort(nums); //最小值大于0或最大值小于0,显然是无法找到需要的组合 if (nums[0] > 0 || nums[len-1] < 0) { return result; } //考虑到组合的和为0,因此整个组合不可能全部为负数或正数 //用于存储负数,及负数出现的次数 HashMap<Integer, Integer> negativeMap = new HashMap<>(); ArrayList<Integer> negativeList = new ArrayList<>(); //用于存储正数,及正数出现的次数 HashMap<Integer, Integer> positiveMap = new HashMap<>(); ArrayList<Integer> positiveList = new ArrayList<>(); //存储是否出现0 int numOfZero = 0; for (int num : nums) { if (num < 0) { addNumToCollections(num, negativeMap, negativeList); } else if (num > 0) { addNumToCollections(num, positiveMap, positiveList); } else { ++numOfZero; } } //出现3个以上的0,显然0 0 0的组合满足条件 if (numOfZero >= 3) { List<Integer> answer = new ArrayList<>(); for (int i = 0; i < 3; ++i) { answer.add(0); } result.add(answer); } //每次先取一个负数,再取一个正数 for (int i = 0; i < negativeList.size(); ++i) { for (int j = 0; j < positiveList.size(); ++j) { int negative = negativeList.get(i); int positive = positiveList.get(j); //求出需要的第3个数 int complete = 0 - negative - positive; boolean addFlag = false; //需要的数小于0,并且存在 if (complete < 0 && negativeMap.containsKey(complete)) { //需要的数与主动取出的负数不一致时,它的下标必须大于主动取得负数的下标,否则会出现重复的组合 if ((complete != negative && negativeList.indexOf(complete) > i)|| //需要的数与主动取出的负数一致,那么要求这个负数至少出现两次以上 (complete == negative && negativeMap.get(negative) > 1)) { addFlag = true; } //所需的数为正数,类似 } else if (complete > 0 && positiveMap.containsKey(complete)){ if ((complete != positive && positiveList.indexOf(complete) > j) || (complete == positive && positiveMap.get(positive) > 1)) { addFlag = true; } } else if (complete == 0 && numOfZero > 0){ addFlag = true; } if (addFlag) { addAnswerToResult(negative, positive, complete, result); } } } return result; } private void addNumToCollections(int num, Map<Integer, Integer> map, List<Integer> list) { if (map.containsKey(num)) { map.replace(num, map.get(num), map.get(num)+1); } else { map.put(num, 1); list.add(num); } } private void addAnswerToResult(int negative, int positive, int complement, List<List<Integer>> result) { List<Integer> answer = new ArrayList<>(); answer.add(negative); answer.add(positive); answer.add(complement); result.add(answer); }}
这个方法可以得到正确结果,但是会超时。整个算法仅看for循环似乎复杂度是O(
2、类似于求最大水位的问题
个人记录-LeetCode 11. Container With Most Water
public class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> result = new ArrayList<>(); if (nums == null || nums.length < 3) { return result; } int len = nums.length; Arrays.sort(nums); if (nums[0] > 0 || nums[len-1] < 0) { return result; } //轮询数组中的每一个数字,为了避免重复 //找到在这个数字之后,出现的另外两个数字,构成组合 for (int i = 0; i < len-2;) { int firstIndex = i + 1; int lastIndex = len - 1; while (firstIndex < lastIndex) { int curr = nums[firstIndex] + nums[lastIndex] + nums[i]; //类似于求水位问题,当前的和大于0,降低高位的下标 if (curr > 0) { do { --lastIndex; //跳过重复的值 } while (firstIndex < lastIndex && nums[lastIndex] == nums[lastIndex+1]); //当前的和小于0,增加低位的下标 } else if (curr < 0){ do { ++firstIndex; } while(firstIndex < lastIndex && nums[firstIndex] == nums[firstIndex-1]); } else { addAnswerToResult(nums[firstIndex], nums[lastIndex], nums[i], result); //等于0时,找出新的两个数,与当前数字构成组合 //低位增加、高位减小才有可能满足条件 do { ++firstIndex; }while(firstIndex < lastIndex && nums[firstIndex] == nums[firstIndex-1]); do { --lastIndex; }while (firstIndex < lastIndex && nums[lastIndex] == nums[lastIndex+1]); } } //跳过重复的组合 do{ ++i; }while(i < nums.length && nums[i] == nums[i-1]); } return result; } private static void addAnswerToResult(int first, int last, int complement, List<List<Integer>> result) { List<Integer> answer = new ArrayList<>(); answer.add(first); answer.add(last); answer.add(complement); result.add(answer); }}
这个方法的复杂度是O(
0 0
- 个人记录-LeetCode 15. 3Sum
- 个人记录-LeetCode 16. 3Sum Closest
- 个人记录-LeetCode 1.Two Sum
- 个人记录-LeetCode 18. 4Sum
- 个人记录-LeetCode 39. Combination Sum
- 个人记录-LeetCode 40. Combination Sum II
- 个人记录-LeetCode 64. Minimum Path Sum
- leetcode记录-Two Sum
- LeetCode 15. 3Sum
- LeetCode --- 15. 3Sum
- [Leetcode] 15. 3Sum
- 【LeetCode】15. 3Sum
- 【leetcode】15. 3sum
- 【leetcode】15. 3Sum
- [leetcode] 15. 3Sum
- leetcode 15. 3Sum
- leetcode 15. 3Sum
- leetcode 15. 3Sum
- 第2节--Python环境配置
- 绘王绘画板怎么用
- 《OpenCV3编程入门》学习笔记十:角点检测
- Weibo开发中的error:redirect_uri_mismatch问题解决
- iOS常见问题之 C字符串与NSString之间的转换
- 个人记录-LeetCode 15. 3Sum
- 产品经理,能否让我过一个不加班的程序员节!
- 面试前应该了解公司的哪些信息?
- git设置代理
- CRON表达式
- Java生成和操作Excel文件(读、写)
- main:处理命令行选项 知识点总结
- 万年历的部分功能
- spark基于用户的协同过滤算法与坑点,提交job