持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
前言
算法的重要性不言而喻!区分度高!
现在学习的门槛低了,只有能上网每个人都可以学编程!培训班6个月就可以培养出来能干活的人,你怎么从这些人中脱颖而出?没错!就是学算法,学一些底层和基础的东西。
说的功利点是为了竞争,卷死对手。真心话说就是能提高自己的基础能力,为技术可持续发展做好充分的准备!!!
提前入门学习书籍:CPrimerPlus、大话数据结构
刷题网站
我是按照代码随想录提供的刷题顺序进行刷题的,大家也可以去刷leetcode最热200道,都可以
刷题嘛,最重要的就是坚持了!!!
画图软件
OneNote
这个要经常用,遇见不懂的流程的话就拿它画一画!
笔记软件
Typoral
题目
解析
暴力思路
三层for循环 都可以想到的方法,但是它行不行呢?
public class TheSumOfThreeNumbers {
public static void main(String[] args) {
int[] nums = {-1, 0, 1, 2, -1, -4};
ArrayList<List<Integer>> arrayList = new ArrayList<>();
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 sum = nums[i] + nums[j] + nums[k];
if (sum == 0){
arrayList.add(Arrays.asList(nums[i],nums[j],nums[k]));
}
}
}
}
arrayList.forEach(x -> System.out.println(x));
}
}
不太行,因为[-1,0,1],[0,1,-1]]算是重复的啦,换位置也不行
双指针
这题的确不好想,看题解中的例子是使用指针的方法:
- 首先对数组排序
- 定义二个指针
- 循环for目的是遍历数组,i从下标0开始
- 第一个指针left从i+1开始,代表第二个数
- 第二个指针right在数组尾部,代表第三个数
相当于 a = nums[i],b = nums[left],c = nums[right]。
接下来如何移动left 和right呢?
想起我们刚开始对数组做的排序了吗?如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了所以right下标就应该向左移动,这样才能让三数之和小一些。
nums[i] + nums[left] + nums[right] < 0 说明三数之和小了,left就向右移动,才能让三数之和大一些,直到left与right相遇为止。
时间复杂度:O(n^2)。
public static List<List<Integer>> threeSum(int[] nums) {
ArrayList<List<Integer>> result = new ArrayList<>();//存放结果集,格式为[[],[],[]....]
Arrays.sort(nums); //对目标数据进行排序
if (nums == null || nums.length < 3) {
return result;
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
return result; //临界条件的一些判断,如果排序后的第一个数都大于0那么三数之后不可能为0
}
/**
* 加上i > 0是因为第一个数没和前一个数比较,会出现数组越界
* 为i-1是因为,i是增加的,它要和后面的数比较看是否相等
*/
if (i > 0 && nums[i] == nums[i - 1]) { //
continue; //这里是对i的去重
}
int left = i + 1; //左指针
int right = nums.length - 1; //右指针
while (right > left) {
int sum = nums[i] + nums[left] + nums[right];
if (sum > 0) {
right--; //和大于0,说明加的太大了,只能让right左移
} else if (sum < 0) {
left++; //和小于0,说明加的太小了,只能让left右移
} else {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));//等于0,加入结果集
while (right > left && nums[left] == nums[left + 1]) left++;//对右指针去重
while (right > left && nums[right] == nums[right - 1]) right--;//对左指针去重
right--;//往左移动
left++;//往右移动
}
}
}
return result;
}
代码中也有详细的解释,实在不明白的话可以dubug一下