1. 程式人生 > >LeetCode刷題筆記(一)

LeetCode刷題筆記(一)

問題一:兩數相加

給定兩個非空連結串列來表示兩個非負整數,位數按照逆序方式儲存,它們的每個節點只儲存單個數字,將兩數相加返回一個新的連結串列。

例項:

輸入:(2 -> 4->3) + (5->6->4)

輸出:7 -> 0 - >8

原因:342 + 465 = 807

基本思路梳理:首先,建立空節點作為記錄新建連結串列的頭結點,依次遍歷兩個連結串列,carry表示進位,計算當前位的和,並判斷是否有進位,原有連結串列節點移動,新建連結串列節點後移。當遍歷完其中某一個連結串列後,再接上後一個連結串列。

程式碼實現部分:Java

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) { val = x; }  * }  */ class Solution {     public ListNode addTwoNumbers(ListNode l1, ListNode l2) {         int carry = 0;//進位         ListNode head = new ListNode(0);//儲存頭結點         ListNode cur = head;

//公共部分的和求解         while(l1!=null&&l2!=null){             int sum = (l1.val + l2.val +carry)%10;             ListNode tmp = new ListNode(sum);             if((l1.val + l2.val +carry)>=10) {                 carry = 1;             }else carry = 0;                          cur.next = tmp;             cur = cur.next;             l1 = l1.next;             l2 = l2.next;         }

//各自多餘部分的複製         while(l1!=null){             if(carry==1){                 ListNode end = new ListNode((l1.val+1)%10);                 cur.next = end;                 if(l1.val+1==10)                     carry = 1;                 else carry = 0;                 l1 = l1.next;                 cur = cur.next;             }else{                 ListNode end = new ListNode(l1.val);                 cur.next = end;                 l1 = l1.next;                 cur = cur.next;             }         }                               while(l2!=null){             if(carry==1){                 ListNode end = new ListNode((l2.val+1)%10);                 cur.next = end;                 if(l2.val+1==10)                     carry = 1;                 else carry = 0;                 l2 = l2.next;                 cur = cur.next;             }else{                 cur.next = l2;                 l2 = l2.next;                 cur = cur.next;             }         }

//進位為1時,還需在最終部分加上值為1的節點          if(carry==1){                 ListNode end = new ListNode(1);                 cur.next = end;         }         return head.next;     } }

優化版本:無論連結串列長度相同還是不同,將短的連結串列對應長連結串列的部分視為0,繼續加,簡化程式碼量。

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) { val = x; }  * }  */ class Solution {     public ListNode addTwoNumbers(ListNode l1, ListNode l2) {         int tmp;int flag = 0;         ListNode head = new ListNode(0);         ListNode result = head;         while(l1!=null||l2!=null){             int x = (l1!=null) ?l1.val:0;             int y = (l2!=null) ?l2.val:0;             tmp=flag+x+y;                 flag=tmp/10;             result.next = new ListNode(tmp%10);             result=result.next;             if(l1!=null)l1=l1.next;             if(l2!=null)l2=l2.next;         }         if(flag>0)  result.next = new ListNode(flag);         return head.next;     } }

問題二:螺旋矩陣

給定一個包含m x n個元素的矩陣(m行,n列),請按照順時針螺旋順序,返回矩陣中的所有元素。

例項1:

輸入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
輸出: [1,2,3,6,9,8,7,4,5]

示例 2:

輸入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
輸出: [1,2,3,4,8,12,11,10,9,5,6,7]

參考leecode給出的解法:

方法一:確定每走一次迴圈需要哪些下標變化及趨勢,分為四部分:行不變列遞增,行遞增列不變,行不變列遞減,行遞減列不變,需要儲存對應下標的遞增步長,其邊界條件是到達行末列末行首列首,或者已經遍歷過的。

class Solution {     public List<Integer> spiralOrder(int[][] matrix) {         List<Integer> res = new ArrayList<>();         if(matrix.length==0)             return res;         int R = matrix.length,C = matrix[0].length;         boolean[][] seen = new boolean[R][C];         int[] dr = {0,1,0,-1};         int[] dc = {1,0,-1,0};         int di=0,r= 0,c = 0,cr = 0,cc = 0;         for(int i = 0;i<R*C;i++){             res.add(matrix[r][c]);             seen[r][c] = true;             cr = r + dr[di];             cc = c + dc[di];             if(0<=cr&& cr<R&& 0<=cc &&cc<C && !seen[cr][cc]){                 r = cr;                 c = cc;             }else{                 di = (di+1)%4;                 r += dr[di];                 c += dc[di];             }         }         return res;     } }

方法二:Layer-by-Layer(層層遍歷)

記錄每層行首行末編號以及列首列末編號,控制遍歷層次。

class Solution {     public List<Integer> spiralOrder(int[][] matrix) {         List<Integer> res = new ArrayList<>();         if(matrix.length==0)             return res;         int r1 = 0,r2 = matrix.length-1;         int c1 = 0,c2 = matrix[0].length-1;         while(r1<=r2&&c1<=c2){             for(int c=c1;c<=c2;c++) res.add(matrix[r1][c]);             for(int r=r1+1;r<=r2;r++) res.add(matrix[r][c2]);             if(r1<r2&&c1<c2){                 for(int c=c2-1;c>=c1;c--) res.add(matrix[r2][c]);                 for(int r=r2-1;r>r1;r--) res.add(matrix[r][c1]);             }             r1++;             r2--;             c1++;             c2--;         }         return res;     } }

問題三:螺旋矩陣II

給定一個正整數 n,生成一個包含 1 到 n2 所有元素,且元素按順時針順序螺旋排列的正方形矩陣。

示例:

輸入: 3
輸出:
[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]

class Solution {     public int[][] generateMatrix(int n) {         int[][] res = new int[n][n];                  int rowStart = 0;         int rowEnd = n-1;         int colStart = 0;         int colEnd = n-1;         int num = 1;                  while(rowStart<=rowEnd && colStart<=colEnd){             for(int i = colStart;i<=colEnd;i++){                 res[rowStart][i] = num++;             }             rowStart++;             for(int i = rowStart;i<=rowEnd;i++){                 res[i][colEnd] = num++;             }             colEnd--;             for(int i = colEnd;i>=colStart;i--){                 res[rowEnd][i] = num++;             }             rowEnd--;             for(int i = rowEnd;i>= rowStart;i--){                 res[i][colStart] = num++;             }             colStart++;         }         return res;     } }