LeetCode刷题记录(一)
最近开始在LeetCode上面做题,想想应该做一个记录,以便以后看到类似的问题及时查阅,同时也能够将做题时的思路记录下来,将这些思路整理归纳,形成一套我自己的解题思路。当然,算法题只做一次是不够的,需要多次的练习,可能每次的想法都不太一样,在这里我只将当时做题的想法记录下来,不一定是这道题目的最优解,以后发现更好的解法的时候我也会及时更新。因为是刚开始做题,所以除了题目特殊要求之外,我暂时还未完全考虑优化算法的时间和空间复杂度,后续再做的时候就需要考虑这方面的问题了。
我没有按照题目的顺序往下面做,而是先挑选卡片进行专项练习的,最近我做的是数组和字符串卡片下面的题目,也是相对较为简单的内容。
1、寻找数组的中心索引
题目:
我的思路:
- 首先需要计算数组所有元素的和sum;
- 然后遍历数组每个元素,计算剔除当前元素后数组所有元素的和tmp;
- 计算当前元素左侧所有元素的和;
- 如果左侧元素的和*2等于tmp,说明当前元素左右两侧的和相同,当前元素的索引即是答案
按照这个思路实现的代码如下:
class Solution {
public int pivotIndex(int[] nums) {
if(nums.length == 0) {
return -1;
}
//1、计算数组所有元素的和
int sum = 0;
for(int num : nums) {
sum += num;
}
int index = -1;
//2、遍历数组
for(int i = 0; i < nums.length; i++) {
//3、计算剔除当前元素后数组所有元素的和tmp
int tmp = sum - nums[i];
//4、计算当前元素左侧所有元素的和
int tmpSum = 0;
for(int j = 0; j < i; j++) {
tmpSum += nums[j];
}
//5、如果左侧元素的和*2=tmp说明当前元素左右两侧元素的和相等,当前元素的索引就是中心索引
if(tmpSum * 2 == tmp) {
index = i;
break;
}
}
return index;
}
}
2、至少是其他数字两倍的最大数
题目:
我的思路:
- 首先需要获取到这个数组的最大元素;
- 然后遍历数组中除了最大元素的所有元素,如果某个元素*2>最大元素的话,说明不符合题目要求,可以直接结束;
- 如果数组中除了最大元素之外所有元素都满足*2≤最大元素,说明找到了符合条件的元素,该元素的索引就是答案。
按照这个思路实现的代码如下:
class Solution {
public int dominantIndex(int[] nums) {
int biggest = 0, bigIndex = -1;
//1、计算数组中元素的最大值及其索引
for(int i = 0; i < nums.length; i++) {
if(nums[i] > biggest) {
biggest = nums[i];
bigIndex = i;
}
}
int index = -1, count = 0;
//2、遍历数组
for(int i = 0; i < nums.length; i++) {
if(i != bigIndex) {
//3、如果存在数组元素的两倍比最大值大的情况,说明不符合条件直接跳出循环
if(nums[i] * 2 > biggest) {
break;
} else {
count++;
}
}
}
//4、获取结果
if(count == nums.length - 1) {
index = bigIndex;
}
return index;
}
}
值得注意的是,在这种实现方式里我定义了一个变量count,这个变量相当于一个计数器,在遍历数组的时候,如果数组元素的值*2≤最大值,那么count就会递增,在最后我增加了一个判断,如果count等于数组的长度减1说明数组已经全部遍历完成(不包括最大的元素),那么最大元素的索引就是最后的答案。
3、加一
题目:
之前的思路:
- 遍历这个数组,计算这个数组代表的整数;
- 将这个整数+1,得到新的整数;
- 将新的整数拆解成数组,得到最后的结果。
这种实现方式表面上看实现了题目中要求的功能,但是实际上是没有考虑数据类型最大值的情况,以int类型为例,我们都知道在Java中int类型是32位的,最大值是2,147,483,647
,也就是说如果遍历数组得到的整数大于这个最大值,那么+1得到的结果也就毫无意义了。那如果我们将计算结果定义为long型,也是不能解决问题的,因为long型也有最大值的问题。那浮点型呢?也是不行的,而且浮点型还会有精度的问题,所以说这个思路是错误的。
后来我又想到了一个新的思路,既然这个数组每一位都代表了一个整数的每一位,那么我们能不能就直接按照加法的规则去计算结果呢?什么是加法的规则?最简单的就是如果这个数最后一位+1≥10,那么最后一位置0,它需要向前进位,让前面的数也+1,以此类推。如果计算到第一位仍然需要进位,那么就在数字最前面补1,这样一来解题的思路就很清晰了。
改进后的思路:
- 判断数组最后一位+1是否<10,如果是,则只需要将最后一位+1即可;
- 如果数组最后一位+1≥10,那么就将最后一位置为0并向前进位,判断前一位+1是否≥10,如果是,仍然置0并向前进为,以此类推;
- 如果得到的数组第一位是0,说明需要新建一个数组,数组长度为原数组长度+1,并且这个数组的第一位为1,其余位均为0;
- 如果得到的数组第一位不为0,只需要将最后需要+1的值+1即可。
按照这个思路实现的代码如下:
class Solution {
public int[] plusOne(int[] digits) {
int len = digits.length;
int[] rslt = null;
if(digits[len - 1] + 1 < 10) {
//1、如果数组最后一个元素(也就是整数最后一位)+1小于10,说明无需进位,直接加1即可
digits[len - 1] = digits[len - 1] + 1;
rslt = digits;
} else {
//2、如果数组最后一个元素(也就是整数最后一位)+1大于等于10,说明需要进位
//3、因为需要进位,所以从最后一位开始向前遍历,如果当前位+1大于等于10,则将当前位的值置为0
int i = len - 1;
while(i >= 0 && digits[i] + 1 >= 10) {
digits[i] = 0;
i--;
}
//3、判断是否所有的位数都置为0,如果是,说明数组的形式类似于[9,9,9]
//那么最后的结果应该是一个新的数组[1,0,0,0],需要新写一个数组,数组长度+1,数组第一位为1,其余位为0
if(i == -1) {
rslt = new int[digits.length + 1];
rslt[0] = 1;
for(int j = 1; j < rslt.length; j++) {
rslt[j] = 0;
}
} else {
//4、并不是所有位数都为0,所以只需将需要+1的位数+1即可
digits[i] = digits[i] + 1;
rslt = digits;
}
}
return rslt;
}
}