1.
思路:
因為楊輝三角是由二維數組構成,所以要先創建一個二維數組,如何用順序表表示二維數組,可以通過List<List<Interger>>來表示一個二維數組,可以這樣理解:先創建一個一維數組List,然后這個一維數組里面存放的元素類型是:<List<Integer>>,即接收整型的一維數組,所以一個一維數組中每個元素存的還是一維數組,那么就相當于二維數組了。
然后楊輝三角每行的第一列為1,則add(1)即可,中間為上一行對齊的兩個元素之和,所以要先通過對二維數組get得到上一行的數組,再通過對上一行的數組get得到對齊的那兩個元素,最后將和add到這一行的一維數組里,如此類推
最后每一行的最后一列元素也是1,因為add的底層實現是尾插,所以我們直接add(1)即可,最后再將這一行的一維數組add到二維數組里
class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> list=new ArrayList();//二維數組List<Integer> list1=new ArrayList<>();//一維數組list1.add(1);list.add(list1);for (int i = 1; i < numRows; i++) {//第一列List<Integer> curRow=new ArrayList<>();curRow.add(1);//中間List<Integer> preRow=list.get(i-1);for (int j = 1; j < i; j++) {int a=preRow.get(j-1);int b=preRow.get(j);curRow.add(a+b);}//最后一列curRow.add(1);list.add(curRow);}return list;}
}
2.
思路:
看到求中間的東西,大概率會用到快慢指針,即當慢指針走一步,快指針走兩步,當快指針到達終點時,慢指針剛好在中間,因為很簡單的公式:路程=速度*時間;時間t相等,v快=2v慢,s=v快*t,v慢*t=1/2s
當結點為奇數個數時,剛好為中間的結點,當結點為偶數個數,為中間的第二個結點,根據快慢指針一個走兩步,一個走一步,剛剛好都滿足,所以就不用分類討論了
什么時候停止指針移動呢,根據示例1和2,在示例1中,當快指針在5這里停止,在示例2中,當快指針在6的后面(即null)這里停止,所以循環條件為fast!=null&&fast.next!=null,注意&&前后兩個條件不能換,必須先fast!=null再fast.next!=null,因為互換的話,當fast==null時,fast.next會報異常
class Solution {public ListNode middleNode(ListNode head) {if(head==null){return head;}ListNode slow=head;ListNode fast=head;while(fast!=null&&fast.next!=null){slow=slow.next;//走一步fast=fast.next.next;//走兩步}return slow;}
}
3.
思路:
需要兩個指針,一個記錄當前結點cur,一個記錄前面的那個結點precur,一開始都指向頭結點head。如果cur的val等于傳入的val,則先將cur往后移動一位,然后precur.next指向cur;否則precur走到cur的位置,cur往后移一步,循環條件為cur!=null,這是一般情況的代碼
如果一開始頭結點就等于val,即示例3的情況,那么按照上面的代碼就不能將頭結點移除,所以我們要判斷一開始頭結點是否為val,如果為val,則新頭結點為頭結點的后一個,因為移除完后的新頭結點有可能仍然等于val,所以不是用if而是while,如果頭結點為null,則說明全是val,如示例3的情況,此時就返回新頭結點(也就是null)
一般都是先考慮正常情況,然后再來考慮特殊情況
class Solution {public ListNode removeElements(ListNode head, int val) {if(head==null){return head;}//解決一開始頭結點的值就為valwhile(head.val==val){head=head.next;if(head==null){return head;}}//說明此時頭結點一定不為valListNode cur=head;//當前結點ListNode precur=head;//前結點while(cur!=null){if(cur.val==val){cur=cur.next;precur.next=cur;}else{precur=cur;cur=cur.next;}}return head;}
}
4.
思路:
因為是反轉,所以可以確定的是,第一個結點反轉后一定是最后一個結點,所以我們要將頭結點的next改為null,但改之前要記錄頭結點的下一個結點。然后采用每遍歷一個結點就進行頭插,即該結點cur的next指向頭結點,但修改next的指向時,要先將原來的next指向的結點進行保存,保存到curN,然后頭插完,cur=curN,循環條件為cur!=null
class Solution {public ListNode reverseList(ListNode head) {if(head==null){return head;}//必要處理ListNode cur=head.next;//第一步:記錄頭結點的next結點head.next=null;//第二步:頭結點的next改為null//循環遍歷,使用頭插while(cur!=null){ListNode curN=cur.next;//循環中的第一步:記錄下一個結點cur.next=head;//第二步:當前結點頭插到頭結點之前head=cur;//第三步:新的頭結點為當前結點cur=curN;//第四步:當前結點后移到原來的下一個結點位置}return head;}
}
5.
思路:
法一:可以利用我們剛剛上面那道題的代碼,先將鏈表反轉,再遍歷第k個結點即可
法二:遍歷兩次,第一次求長度len,第二次遍歷到第len-k個結點即可
法三:利用集合順序表arraylist,遍歷一次,用add將里面所有的元素放進順序表里,然后再get(arraylist.size()-k)即可
法四:快慢雙指針,先提前讓快指針走k步,然后慢指針和快指針以相同的速度每次走一步,當快指針走到最后時,慢指針的位置即為倒數第k個結點
示例代碼(法一)
class Solution {public int kthToLast(ListNode head, int k) {if(head==null){return -1;}//反轉鏈表ListNode cur=head.next;head.next=null;while(cur!=null){ListNode curN=cur.next;cur.next=head;head=cur;cur=curN;}//然后找ListNode node=head;for(int i=1;i<k;i++){node=node.next;}return node.val;}
}