160.Intersection of Two Linked Lists
注意,鏈表結點相同意味着他們的值相同,下一個結點也相同
方法1:暴力法
方法2:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null)
return null;
ListNode pa=headA,pb=headB;
while(pa!=pb)
{
pa=pa==null?headA:pa.next;
pb=pb==null?headB:pb.next;
}
return pa;
}
}
方法3哈希法:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> set=new HashSet();
while (headA!=null){
set.add(headA);
headA=headA.next;
}
while (headB!=null){
if(set.contains(headB))
return headB;
headB=headB.next;
}
return null;
}
}
206 Reverse Linked List
頭插法:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode newHead = null;
while (head != null) {
ListNode next = head.next;
head.next = newHead;//畫圖理解
newHead = head;
head = next;
}
return newHead;
}
}
遞歸解法:
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
ListNode newHead = reverseList(next);
next.next = head;
head.next = null;
return newHead;
}
21. 合併兩個有序鏈表
遞歸解法:
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}
83. 刪除排序鏈表中的重複元素
遞歸解法:
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null||head.next==null)
return head;
head.next=deleteDuplicates(head.next);
return head.val==head.next.val?head.next:head;
}
}
19. 刪除鏈表的倒數第N個節點
①解法1:兩次遍歷,統計鏈表的長度
②快慢指針
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first = dummy;
ListNode second = dummy;
// Advances first pointer so that the gap between first and second is n nodes apart
for (int i = 1; i <= n + 1; i++) {
first = first.next;
}
// Move first to the end, maintaining the gap
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
24. 兩兩交換鏈表中的節點
①解法一 遞歸:
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null||head.next==null)
/*先判斷head在判斷next*/
return head;
ListNode next= head.next;
head.next=swapPairs(head.next.next);
next.next=head;
return next;
}
}
②解法二迭代:
public ListNode swapPairs(ListNode head) {
ListNode node = new ListNode(-1);
node.next = head;
ListNode pre = node;
while (pre.next != null && pre.next.next != null) {
ListNode l1 = pre.next, l2 = pre.next.next;
ListNode next = l2.next;
l1.next = next;
l2.next = l1;
pre.next = l2;
pre = l1;
}
return node.next;
}
445. 兩數相加 II
逆序處理:用棧,carray表示進位
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> l1Stack = buildStack(l1);
Stack<Integer> l2Stack = buildStack(l2);
ListNode head = new ListNode(-1);
int carry = 0;
while (!l1Stack.isEmpty() || !l2Stack.isEmpty() || carry != 0) {
int x = l1Stack.isEmpty() ? 0 : l1Stack.pop();
int y = l2Stack.isEmpty() ? 0 : l2Stack.pop();
int sum = x + y + carry;
ListNode node = new ListNode(sum % 10);
node.next = head.next;
head.next = node;
carry = sum / 10;
}
return head.next;
}
private Stack<Integer> buildStack(ListNode l) {
Stack<Integer> stack = new Stack<>();
while (l != null) {
stack.push(l.val);
l = l.next;
}
return stack;
}
}
2. 兩數相加
這裏直接遍歷就可,做法也是一樣,t表示進位
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(-1), pre = dummyHead;
int t = 0;
while (l1 != null || l2 != null || t != 0) {
if (l1 != null) {
t += l1.val;
l1 = l1.next;
}
if (l2 != null) {
t += l2.val;
l2 = l2.next;
}
pre.next = new ListNode(t % 10);
pre = pre.next;
t /= 10;
}
return dummyHead.next;
}
}
234. 迴文鏈表
快慢指針,逆轉鏈表
class Solution {
public:
//題解:快慢指針法,快指針走兩步,慢指針走一步,找到鏈表的中點。然後,翻轉後半部分。最後從頭、中點開始判斷是否相同。
bool isPalindrome(ListNode* head) {
if(!head||!head->next)return true;
ListNode *fast=head,*slow=head,*pre=nullptr;
//1、找到鏈表的中點,鏈表長度奇偶不影響
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
}
//2、將slow之後鏈表進行斷開且反轉,最後翻轉完成之後pre指向反轉鏈表的頭節點
while(slow){
ListNode *p=slow->next;
slow->next=pre;
pre=slow;
slow=p;
}
//3、前後鏈表進行比較,注意若爲奇數鏈表,後半部分回比前部分多1一個節點,然而我們只比較相同長度的節點值,巧妙地避開這點判斷
while(head&&pre){
if(head->val!=pre->val)return false;
head=head->next;
pre=pre->next;
}
return true;
}
};
725. 分隔鏈表
注意一個地方:
ListNode temm=temp; 比如這裏,temm和temp屬於同一個結點,如果把temm的next設置爲空,那麼temp的next也爲空
題目描述:把鏈表分隔成 k 部分,每部分的長度都應該儘可能相同,排在前面的長度應該大於等於後面的。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode[] splitListToParts(ListNode root, int k) {
ListNode p=root;
ListNode[] listArrary=new ListNode[k];
int listLength=0,avgLength=0,leftLength=0;
while(p!=null){
p=p.next;
listLength++;
}
avgLength=listLength/k; //*每一個數組元素的長度*/
leftLength=listLength%k; //*剩餘的長度 */
if(listLength<=k){
ListNode temp=root;
for(int i=0;i<k;i++){
if(temp!=null){
listArrary[i]=temp; // 注意 listArrary[i]=temp; 那麼這兩個就是同一個結點
ListNode temm=temp.next; //這裏一定要暫存temp.next的結點;
listArrary[i].next=null;
temp=temm;
}
else
listArrary[i]=null;
}
return listArrary;
}
for(int i=0;i<k;i++){
listArrary[i]=root;
for(int j=0;j<avgLength-1;j++){
root=root.next;
}
ListNode temp=null;
if(leftLength!=0){ //看看是否還有剩餘長度
root=root.next;
temp=root.next;
root.next=null;
leftLength--;
}
else
{
temp=root.next;
root.next=null;
}
root=temp;
}
return listArrary;
}
}
328. 奇偶鏈表
畫圖快速理解
class Solution {
public ListNode oddEvenList(ListNode head) {
if(head==null)
return head;
ListNode first=head,two=head.next,third=two;
//分別指向奇結點和偶節點,third用來連接成功後的奇偶鏈表
while(two!=null&&two.next!=null){
//two不爲空,first必不爲空,first爲不空,two可能爲空
//two指針一定在first後面,所以判斷two就可以了
first.next=first.next.next;
first=first.next;
two.next=two.next.next;
two=two.next;
}
first.next=third;
return head; //返回頭指針
}
}