1. 程式人生 > >03、位元組跳動-連結串列與樹

03、位元組跳動-連結串列與樹

1、合併兩個有序連結串列

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode listNode = new ListNode(0);
    ListNode firstNode = listNode;

    while (l1 != null && l2 != null) {
        if (l1.val <= l2.val) {
            listNode.next = l1;
            l1 = l1.next;
        } else {
            listNode.next = l2;
            l2 = l2.next;
        }
        listNode = listNode.next;
    }
    while (l1 != null) {
        listNode.next = l1;
        l1 = l1.next;
        listNode = listNode.next;
    }
    while (l2 != null) {
        listNode.next = l2;
        l2 = l2.next;
        listNode = listNode.next;
    }
    return firstNode.next;
}

原文:https://blog.csdn.net/hocsoul/article/details/80048940 

 

2、反轉連結串列

public ListNode reverseList3(ListNode pHead){
	if(pHead==null || pHead.next == null){ //如果沒有結點或者只有一個結點直接返回pHead
		return pHead;
	}
	ListNode pNext = pHead.next; //儲存當前結點的下一結點
	pHead.next = null; //打斷當前結點的指標域
	ListNode reverseHead = reverseList3(pNext); //遞迴結束時reverseHead一定是新連結串列的頭結點
	pNext.next = pHead; //修改指標域
	return reverseHead;
}

原文:https://blog.csdn.net/u013132035/article/details/80589657

 

3、兩數相加

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        if (l1 == null) {
            return l2;
        }

        if (l2 == null) {
            return l1;
        }

        ListNode p1 = l1;
        ListNode p2 = l2;
        ListNode root = new ListNode(0); // 頭結點
        ListNode r = root;
        root.next = l1;

        int carry = 0; // 初始進位
        int sum;
        while (p1 != null && p2 != null) {
            sum = p1.val + p2.val + carry;
            p1.val = sum % 10; // 本位的結果
            carry = sum / 10; // 本次進位

            r.next = p1;
            r = p1; // 指向最後一個相加的結點
            p1 = p1.next;
            p2 = p2.next;

        }

        if (p1 == null) {
            r.next = p2;
        } else {
            r.next = p1;
        }

        // 最後一次相加還有進位
        if (carry == 1) {
            // 開始時r.next是第一個要相加的結點
            while (r.next != null) {
                sum = r.next.val + carry;
                r.next.val = sum % 10;
                carry = sum / 10;
                r = r.next;
            }

            // 都加完了還有進位,就要建立一個新的結點
            if (carry == 1) {
                r.next = new ListNode(1);
            }
        }

        return root.next;
    }
}

原文:https://blog.csdn.net/DERRANTCM/article/details/46905467

 

4、排序連結串列

 

package com.main;
 
class ListNode {
    int val;
    ListNode next;
 
    ListNode(int x) {
        val = x;
    }
}
 
public class Main {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        //平分結點,分成兩個分支
        ListNode cur = null, slow = head, fast = head;
        while (fast != null && fast.next != null) {//如果是奇數個結點,多出來的一個結點放在了後面的部分
            cur = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        cur.next = null;
        //每個分支都要排序,然後按序合併
        ListNode l1 = sortList(head);
        ListNode l2 = sortList(slow);
        //按序合併,子分支和大分支都在這裡合併
        return merge(l1, l2);
    }//sortList
 
    public ListNode merge(ListNode l1, ListNode l2) {
        ListNode res = new ListNode(0), p = res;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                res.val = l1.val;
                p.next = l1;//這一句別忘了
                l1 = l1.next;
            } else {
                res.val = l2.val;
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }//while
 
        if (l1 != null) {
            p.next = l1;
        }
        if (l2 != null) {
//            p.next = l2.next;不能是p.next = l2.next
            p.next = l2;
        }
        return res.next;// ListNode res = new ListNode(0)因為第一個結點是0,所以這裡是 res.next,而不是res
    }//merge
 
    public static void main(String[] args) {
        ListNode A = new ListNode(6);
        A.next = new ListNode(2);
        A.next.next = new ListNode(4);
        A.next.next.next = new ListNode(3);
        A.next.next.next.next = new ListNode(5);
 
        Main main = new Main();
        ListNode C = main.sortList(A);
        System.out.println(C);
    }
}

原文:https://blog.csdn.net/u010002184/article/details/76793696 

 

5、環形連結串列 II

public ListNode detectCycle( ListNode head ) {
            if( head == null || head.next == null ){
                return null;
            }
            ListNode fp = head, sp = head;
            while( fp != null && fp.next != null){
                sp = sp.next;
                fp = fp.next.next;
                //判斷是否成環
                if( fp == sp ){  
                    break;
                }
            }
            if( fp == null || fp.next == null ){
                return null;
            }
            //fp到環入口距離 = head到環入口距離
            sp = head;
            while( fp != sp ){
                sp = sp.next;
                fp = fp.next;
            }
            return sp;
    }

連結:https://www.jianshu.com/p/a352d46e7c41

 

6、相交連結串列

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null)
        return null;

    int headALength = 0;
    int headBLength = 0;

    ListNode p = headA;
    while (headA != null){
        ++ headALength;
        headA = headA.next;
    }
    p = headB;
    while (headB != null){
        ++ headBLength;
        headB = headB.next;
    }

    while (headALength > headBLength) {
        headA = headA.next;
        headALength --;
    }

    while (headBLength > headALength) {
        headB = headB.next;
        headBLength --;
    }

    while (headA != null) {
        if (headA == headB)
            return headA;
        headA = headA.next;
        headB = headB.next;
    }
    return null;
}

原文:https://blog.csdn.net/hocsoul/article/details/80151330

 

7、合併K個排序連結串列

public ListNode mergeKLists(ListNode[] lists) {
		if (lists == null || lists.length == 0)
			return null;
		// PriorityQueue 是堆,預設小頂堆
		PriorityQueue<ListNode> min = new PriorityQueue<ListNode>(11, new Comparator<ListNode>() {
			@Override
			public int compare(ListNode o1, ListNode o2) {
				return o1.val - o2.val;
			}
		});
		// 加入所有連結串列的第一個結點,非空
		for (ListNode node : lists)
			if (node != null)
				min.offer(node);
		ListNode head = new ListNode(0);
		ListNode cur = head;
		while (!min.isEmpty()) {
			ListNode temp = min.poll();
			cur.next = temp;
			cur = cur.next;
			// 邊取邊加入
			if (temp.next != null)
				min.offer(temp.next);
		}
		// 注意斷鏈
		cur.next = null;
		return head.next;
	}

原文:https://blog.csdn.net/mine_song/article/details/69501383 

 

8、二叉樹的最近公共祖先

 

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 左右子樹探索時發現目標節點,則通過返回值標記
        if(root == null || p == root || q == root) {
            return root;
        }

        // 檢視左子樹中是否有目標結點,沒有為null
        TreeNode l = lowestCommonAncestor(root.left,p,q);
        // 檢視右子樹中是否有目標結點,沒有為null
        TreeNode r = lowestCommonAncestor(root.right,p,q);

        //都不為空,說明做右子樹都有目標結點,則公共祖先就是本身
        if(l!= null && r!= null) {
            return root;
        }
        // 其他情況,則要繼續向上標記,顯示此節點下邊有目標節點
        return l != null?l:r;
    }
}

原文:https://blog.csdn.net/github_34514750/article/details/52229129

 

9、二叉樹的鋸齒形層次遍歷

 

public class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();

        if (root == null) {
            return result;
        }

        Stack<TreeNode> currLevel = new Stack<TreeNode>();
        Stack<TreeNode> nextLevel = new Stack<TreeNode>();
        Stack<TreeNode> tmp;
        
        currLevel.push(root);
        boolean normalOrder = true;

        while (!currLevel.isEmpty()) {
            ArrayList<Integer> currLevelResult = new ArrayList<Integer>();

            while (!currLevel.isEmpty()) {
                TreeNode node = currLevel.pop();
                currLevelResult.add(node.val);

                if (normalOrder) {
                    if (node.left != null) {
                        nextLevel.push(node.left);
                    }
                    if (node.right != null) {
                        nextLevel.push(node.right);
                    }
                } else {
                    if (node.right != null) {
                        nextLevel.push(node.right);
                    }
                    if (node.left != null) {
                        nextLevel.push(node.left);
                    }
                }
            }

            result.add(currLevelResult);
            tmp = currLevel;
            currLevel = nextLevel;
            nextLevel = tmp;
            normalOrder = !normalOrder;
        }

        return result;

    }
}

參考:https://www.jiuzhang.com/solutions/binary-tree-zigzag-level-order-traversal/