581 Shortest Unsorted Continuous Subarray
问题:这道题目感概颇多,作为第一个array的简单题目就被缠住了。具体内容写在注释里面了。
217 Contains Duplicate
问题:这道题目可以看出有效的数字组合就是0,10,11三种组合。当遍历到某一位是0,下标加1;某一位是1,下标加2.如果到最后只剩下最后一位,并且是0,返回true。
学习:我用递归实现的,看了一个方法用循环实现了,代码简洁。
public boolean isOneBitCharacterV2(int[] bits) {int n = bits.length;int i = 0;while (i < n - 1) {if (bits[i] == 0)i++;elsei += 2;}return i == n - 1;}
代码
118 Pascal’s Triangle
问题:利用杨辉三角形的性质
1 杨辉三角形以正整数构成,数字左右对称,每行由1主键变大,然后变小,变回1;
2 第n行,数字个数为n;
3 第n行,第k个数字为组合数C(k−1)(n−1)C(n−1)(k−1)
4 除每行最左侧与最右侧元素外,每个数字等于它的左上方与右上方数字之和。
代码
695 Max Area of Island
问题:计算小岛的最大面积,与 85 最大矩形面积的区别是:岛的面积只要连通就行,不一定要形成矩形。体现在深度优先搜索上不同。这道题目的精妙还在计算过就让grid[i][j] = 0,这样就不会重复计算了。这是我没有想到的。
代码
628 Maximum Product of Three Numbers
问题:题目的输入是一个整数数组,有正数,有负数。要求输出这些数组中任意三个数字乘积的最大值。
我的想法:最大乘积或者是三个最大正数的乘积,或者是两个具有最大绝对值的负数乘以最大的正数。那么我是不是可以按照数字的绝对值从大到小排序。然后找前三个数字相乘就可以。可以吗?不可以。因为是按照绝对值排序的,所以如果前三个数字恰好都是正数,那也罢了。如果其中一个,原来的数是负数,这个结果就不对了。
学习:思路的第一句是对的。只是处理方法不对。不应该按照数组元素的绝对值排序,这样之后再也找不到对应的原数字,会出问题。应该看到两个具有最大绝对值的负数就是整个数组中最小的两个数。如果能看到这个,就能找到解决方法了。
public int maximumProductV3(int[] nums) {Arrays.sort(nums);int n = nums.length;return Math.max(nums[0]*nums[1]*nums[n-1], nums[n-1]*nums[n-2]*nums[n-3]);}
学习2:最大乘积或者是三个最大正数的成绩,或者是两个具有最大绝对值的负数乘以最大的正数。对这句话可以再理解:找到最大的三个数max1,max2,max3,最小的两个数min1,min2。这应该一次循环就可以搞定,无需排序。有时候离成功就是那么近,目标设立对了,方法却错了。
public int maximumProductV2(int[] nums) {int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;for (int num : nums) {if (num > max1) {max3 = max2;max2 = max1;max1 = num;}else if(num > max2){max3 = max2;max2 = num;}else if(num > max3){max3 = num;}if (num < min1) {min2 = min1;min1 = num;}else if(num<min2){min2 = num;}}return Math.max(max1 * max2 * max3, min1 * min2 * max1);}
代码
414 Third Maximum Number
问题:题目简单,只要注意第三大数字=第三大不同的数字,注意去重。而且题目还给了一组最小的数字-2146473648.
public int thirdMax(int[] nums) {int max1 = Integer.MIN_VALUE,max2=Integer.MIN_VALUE,max3=Integer.MIN_VALUE;int cnt = 0;boolean minvalue = true;for(int num:nums){if (num > max1) {max3 = max2;max2 = max1;max1 = num;cnt++;}else if(num > max2 && num!=max1){max3 = max2;max2 = num;cnt++;}else if(num > max3 && num!=max1 && num!=max2){max3 = num;cnt++;}else if(num==Integer.MIN_VALUE && minvalue){cnt++;minvalue = false;}}return cnt<3?max1:max3;}
643 Maximum Average Subarray I
问题:要找到长度为k的平均值最大的子数组的平均值。只要找到符合条件的子数组即可。题目可以先用for循环,指定子数组的起始位置、结束位置计算;然后会发现超时,为了减少重复的加和步骤,使用滑动窗口的方式。这种窗口滑动的方式在nlp的算法和深度学习中都有使用。
public double findMaxAverageV3(int[] nums, int k) {int n = nums.length;int sum = 0;for (int i = 0; i < k; i++) {sum += nums[i];}int maxSum = sum;for (int i = k; i < n; i++) {sum += nums[i] - nums[i - k];maxSum = Math.max(maxSum, sum);}return (maxSum+0.0)/k;}
448 Find All Numbers Disappeared in an Array
问题:题目简单。输入一个数组,数组元素是[1,n],n是数组长度。有些元素可能重复,有些元素可能没出现。返回没有出现的元素。要求不用额外的空间,用O(n)时间复杂度完成。
我的思路:先使用一个新数组data,长度为n+1。遍历入参nums,设置data[nums[i]]=1。最后遍历data[i]=1就表示i出现过,否则就没有出现。所以关键是标记出出现的元素。可以用数组下标和出现的元素关联起来。如果没有新数组data,那就在原数组nums上做修改。修改的方式有很多种,例如设置为0,设置为负数,原数组值+n等等。我自己实现的修改数组值为0,方式不够漂亮,参考了原数组值+n的方式。
代码
724 Find Pivot Index
问题:从左向右一次选择pivot的index 当选择pivot index 为i的时候leftsum=sum(0,i-1),rightsum=sum(i+1,n-1) ;当选择pinot index 为(i+1)的时候,leftsum=sum(0,i)=sum(0,i-1)+a[i] rigtsum=sum(i+2,n-1)=sum(i+1,n-1)-a[i+1]。注意:左边可以是0个元素,右边也可以是0个元素
学习:更加简洁版本。leftsum + rightsum + nums[i] = sum,所以leftsum和rightsum只要计算一个就可以。只是没有想明白为什么这个版本更慢了。(pivotIndexV2)
代码