leetcode刷题笔记
算法题
1、Product of Array Except Self
题目说明:给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4] 输出: [24,12,8,6]
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
进阶:你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。) 【进阶在第二阶段优化】
解题思路:原本计算出所有数的积然后分别除掉每个数就行了,但原题要求不能用除法,那么,我们就只能使用乘法了。在只使用乘法的情况下想要时间复杂度达到O(n),则需要避免其中重复计算。
假设对于数组 nums[]={2, 3, 4, 5 }, 假设result[]为最后结果,可以得到:

只需要计算出左边A、右边B这两个三角形上每行的乘积,就可以得到result了。如下(n表示输入数组的长度,即 n=input.lenght):
A[0]=1; A[1]=1*input[0]=A[0]*input[0]; A[2]=A[1]*input[1] => A[i]=A[i-1]*input[i-1],i从小到大取值范围为[2, n), B[n-1]=1; B[n-2]=1*input[n-1]=B[n-1]*input[n-1]; B[n-3]=B[n-2]*input[n-2] => B[i]=B[i+1]*input[i+1],i从大到小取值范围为[n-2, 0] result[0]=A[0]*B[0]; result[1]=A[1]*B[1] => result[i]=A[i]*B[i]
以此类推,计算A、B就简单了,完全可以在O(n)内办到,代码实现如下(java):
public class Solution { public static void main(String[] args) { Solution solution = new Solution(); int[] input = new int[] {1,2,3,4}; int[] output = solution.productExceptSelf(input); solution.printResult(output); } private void printResult(int[] result) { StringBuffer sb = new StringBuffer("output["); for(int i=0; i<result.length; i++) { sb.append(result[i]); if(i < result.length-1) { sb.append(","); } } sb.append("]"); System.out.println(sb.toString()); } //算法代码写在这里 public int[] productExceptSelf(int[] nums) { int[] res = new int[nums.length]; int[] left = new int[nums.length]; int[] right = new int[nums.length]; left[0] = 1; for(int i=1; i<nums.length; i++) { left[i] = left[i-1] * nums[i-1]; } right[nums.length-1] = 1; for(int i=nums.length-2; i>=0; i--) { right[i] = right[i+1] * nums[i+1]; } for(int i=0; i<nums.length; i++) { res[i] = left[i] * right[i]; } return res; } }
2、螺旋矩阵
题目说明:给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例:
输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 输出: [1,2,3,6,9,8,7,4,5] 输入: [ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12] ] 输出: [1,2,3,4,8,12,11,10,9,5,6,7]
解题思路:循环走回路,每次回路分为四个方向--向右、向下、向左、向上,每次朝一个方向到达边界就需要执行一些操作--【变换方向,改变该方向上的边界值】,知道遍历完矩阵中的所有元素,即要进行 m*n 次取矩阵元素值添加到返回值列表中,因此循环次数为 m*n ,并且在每次循环中判断走向
代码实现如下,时间复杂度为O(m*n):
//m行n列矩阵 public List<Integer> spiralOrder(int[][] matrix){ List<Integer> order = new ArrayList<Integer>(); int m = matrix.length; int n = matrix[0].length; int len = m*n; //行坐标,列坐标 int row = 0, col = 0; //循环:左最小leftMin++,右最大n-1--,上最小topMin++,下最大m-1-- int leftMin = 0, topMin = 1; //四个方向,向右:row不变,col++;向下:row++,col不变;向左:row不变,col--;向上:row--,col不变 int[][] dir= { {0,1,0,-1},//row的变化值 {1,0,-1,0}//col的变化值 }; //k值改变标志着方向的变化,k%4余数:0-右,1-下,2-左,3-上 int k = 0; for(int i=0; i<len; i++) { //改变row和col的业务逻辑 order.add(matrix[row][col]); row += dir[0][k%4]; col += dir[1][k%4]; switch(k%4) { case 0://右行 //判断是否到达右边界,col=n-1时即到达右边界,此时界限缩小,需要换方向 if(col > n-1) { col = n-1; k++; n--; //向下一 row++; } break; case 1://下行 //判断是否到达下边界,col=n-1时即到达下边界,此时界限缩小,需要换方向 if(row > m-1) { row = m-1; k++; m--; //向左一 col--; } break; case 2://左行 //判断是否到达左边界,col=leftMin时即到达左边界,此时界限缩小,需要换方向 if(col < leftMin) { col = leftMin; k++; leftMin++; //向上一 row--; } break; case 3://上行 //判断是否到达上边界,row=topMin时即到达上边界,此时界限缩小,需要换方向 if(row < topMin) { row = topMin; k++; topMin++; //向右一 col++; } break; } } return order; }

浙公网安备 33010602011771号