leetcode链表算法题实现思路

Posted yrtx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode链表算法题实现思路相关的知识,希望对你有一定的参考价值。

找出两个链表的交点(leetcode160

  一条链表遍历完之后跳转到下一条链表的头节点继续遍历。

       因为当两条链表均被遍历一遍以后,第二次遍历时会同时到达节点相等的地方。如果没有相交的节点,两条链表均遍历两遍后,同时等于null,故返回null。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    ListNode l1 = headA, l2 = headB;
    while (l1 != l2) {
        l1 = (l1 == null) ? headB : l1.next;
        l2 = (l2 == null) ? headA : l2.next;
    }
    return l1;
}

 

链表反转(leetcode206)

  1、非递归

    新建一个头结点newHeadNode,将新头节点的next赋给旧头节点的next,然后将旧头节点赋给新头节点的next并继续迭代。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode newHeadNode = new ListNode(-1);
        while(head != null) {
            ListNode next = head.next;
            head.next = newHeadNode.next;
            newHeadNode.next = head;
            head = next;
        }
        return newHeadNode.next;
    }
}

//更简单的办法

class Solution {
    public ListNode reverseList(ListNode head) {       
    ListNode newHead = null;
      while (head != null) {
         ListNode nextNode = head.next;
         head.next = newHead;
         newHead = head;
         head = nextNode;
      }
      return newHead;
  } 
}
 

  2、递归

    进入递归直到head.next == null,然后回到上一层,此时newHeadNode是最后一个节点,head是倒数第二个节点。将最后一个节点的next指向倒数第二个节点,再将倒数第二个节点的next置空,以防止链表反转后最后一个节点的next不为null。依此类推反复执行head.next.next = head; head.next = null;

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode newHeadNode = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHeadNode;
    }
}

 

归并两个有序链表(leetcoed21)

  1、递归

    比较两个链表的值的大小,若l1.val < l2.val则将l2向后迭代,直至l1或l2为null并返回另一个不为null的节点然后开始逐层拼接。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
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;
        }
    }
}

  2、非递归

    创建一个新的链表并将两条链表逐一添加到新链表中。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode newHeadNode = new ListNode(-1);
        ListNode prev = newHeadNode;
        while(l1 != null && l2 != null) {            
            if(l1.val < l2.val) {
                prev.next = l1;
                l1 = l1.next;
            }else{
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }        
        prev.next = l1 == null ? l2 : l1;//添加最后一个节点     
        return newHeadNode.next;
    }
}

 

 删除排序链表中的重复元素(leetcode83)

  1、非递归

    判断当前链表节点的值与后一个链表的值是否相等,若相同,则将后一个节点的next指向当前节点的next。若不同,则向后迭代直至边界。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode current = head;
        while (current != null && current.next != null) {
          if (current.next.val == current.val) {
              current.next = current.next.next;
          } else {
              current = current.next;
          }
      }
      return head;
    }
}

  2、递归

     递归到最后一层开始返回,如果head.val == head.next.val 则一直返回最后一个节点,如果不同则开始拼接。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null)   return head;
        head.next = deleteDuplicates(head.next);
        return head.next.val == head.val ? head.next : head;
    }
}

 

删除链表的倒数第n个节点(leetcode19)

  1、两次循环

    先遍历获取链表长度,再遍历找到节点的前一个位置。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode curr = new ListNode(-1);
        curr.next = head;
        ListNode first = head;
        int length = 0;
        while(first != null) {
            first = first.next;
            length++;
        }
        length -= n;
        first = curr;
        while(length-- > 0) {
            first = first.next;
        }
        first.next = first.next.next;
        return curr.next;
    }
}

   2、一次循环

    创建两个节点一个指向head,一个指向距head节点 n 个节点的节点,即n+1个节点。当第n+1个节点为null时,指向head的节点刚好指向倒数第n个位置。

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode fast = head;
    while (n-- > 0) {
        fast = fast.next;
    }
    if (fast == null) return head.next;
    ListNode slow = head;
    while (fast.next != null) {
        fast = fast.next;
        slow = slow.next;
    }
    slow.next = slow.next.next;
    return head;
}

 

交换链表中的相邻结点(leetcode24)

  1、递归

    递归至尾节点,然后将最后一个节点的next指向head.next,head指向next.next。完成交换。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode next = head.next;
        head.next = swapPairs(next.next);
        next.next = head;
        return next;
    }
}

    2、非递归

    思路如上,从头开始俩俩交换。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode pre = new ListNode(0);
        pre.next = head;
        ListNode temp = pre;
        while(temp.next != null && temp.next.next != null) {
            ListNode start = temp.next;
            ListNode end = temp.next.next;
            temp.next = end;
            start.next = end.next;
            end.next = start;
            temp = start;
        }
        return pre.next;
    }
}

 

两数相加 II(leetcode445) 

  双栈法。即利用两个栈进行运算并拼接链表。

/**
 * 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) {
        Stack<Integer> stack1 = buildStack(l1);
        Stack<Integer> stack2 = buildStack(l2);
        ListNode head = new ListNode(-1);
        int carry = 0;
        while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {
            int x = stack1.isEmpty() ? 0 : stack1.pop();
            int y = stack2.isEmpty() ? 0 : stack2.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;
    }
}

 

回文链表(leetcode)

  找到中间点,分割,反转,比较。  

public boolean isPalindrome(ListNode head) {
    if (head == null || head.next == null) return true;
    ListNode slow = head, fast = head.next;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    if (fast != null) slow = slow.next;  // 偶数节点,让 slow 指向下一个节点
    cut(head, slow);                     // 切成两个链表
    return isEqual(head, reverse(slow));
}

private void cut(ListNode head, ListNode cutNode) {
    while (head.next != cutNode) {
        head = head.next;
    }
    head.next = null;
}

private ListNode reverse(ListNode head) {
    ListNode newHead = null;
    while (head != null) {
        ListNode nextNode = head.next;
        head.next = newHead;
        newHead = head;
        head = nextNode;
    }
    return newHead;
}

private boolean isEqual(ListNode l1, ListNode l2) {
    while (l1 != null && l2 != null) {
        if (l1.val != l2.val) return false;
        l1 = l1.next;
        l2 = l2.next;
    }
    return true;
}

 

 分割链表(leetcode725)

  先遍历确定链表的长度,然后和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) {
        int N = 0;
        ListNode cur = root;
        while (cur != null) {
            N++;
            cur = cur.next;
        }
        int mod = N % k;
        int size = N / k;
        ListNode[] ret = new ListNode[k];
        cur = root;
        for (int i = 0; cur != null && i < k; i++) {
            ret[i] = cur;
            int curSize = size + (mod-- > 0 ? 1 : 0);
            for (int j = 0; j < curSize - 1; j++) {
                cur = cur.next;
            }
            ListNode next = cur.next;
            cur.next = null;
            cur = next;
        }
        return ret;
    }
}

 

奇偶链表(leetcode328)

  新建一个奇数位置的迭代指针odd和一个偶数位置迭代指针even,然后第一个.next = 第三个;第二个.next = 第四个;并向后迭代最后把偶数头部指向奇数末尾odd。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode oddEvenList(ListNode head) {
        if(head == null) {
            return head;
        }
        ListNode odd = head, even = head.next, evenHead = even;
        while(even != null && even.next != null) {
            odd.next = odd.next.next;
            odd = odd.next;
            even.next = even.next.next;
            even = even.next;
        }
        odd.next = evenHead;
        return head;
    }
}

 

 

以上是关于leetcode链表算法题实现思路的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# leetcode算法题:排序链表

LeetCode Java刷题笔记—206. 反转链表

LeetCode Java刷题笔记—206. 反转链表

#yyds干货盘点# leetcode算法题:合并两个有序链表

数据结构链表经典算法题集锦

算法leetcode面试题 04.03. 特定深度节点链表(多语言实现)