國美供應鏈部門面試筆試題兩道
1: 判斷鏈表是否有環
public class AppTest { public static void main(String[] args) { } public boolean hasCircle(ListNode header) { ListNode p1 = header; ListNode p2 = header; while (true) { // 無環p2先到達終點 if (p2 == null || p2.next == null) { return false; } p2 = p2.next.next; p1 = p1.next; // 有環p2追上p1了 if (p1 == p2) { return true; } } } } class ListNode { public ListNode next; public ListNode() { } }
需要說明算法複雜度,即要證明p2和p1 一定會在某個節點相遇且相遇時p1走了多少步。
2:使用非遞歸實現二叉樹的前序遍歷
public class Main { public static void main(String[] args) { Node[] result = null ; Node node = new Node(1); node.left = new Node(2); node.right = new Node(3); node.left.left = new Node(4); node.left.right = new Node(5); node.right.left = new Node(6); node.right.right = new Node(7); result = pre(node) ; print(result); } public static Node[] pre(Node root) { if (root == null) { return new Node[]{}; } List<Node> nodeList = new ArrayList<>() ; Stack<Node> nodeStack = new Stack<>() ; nodeStack.push(root) ; while (!nodeStack.empty()) { Node curItem = nodeStack.peek(); // 沒有左子樹或者左子樹已經被訪問了 則當前節點出棧 if (curItem.left == null || curItem.visited ==1){ nodeStack.pop(); curItem.visited = 1; nodeList.add(curItem); Node right = curItem.right ; if(right != null){ // 右孩子不爲空 nodeStack.push(right); }else { // 右孩子爲空 則需要標記父節點的左子樹已經被訪問 if (!nodeStack.empty()) { curItem = nodeStack.peek(); curItem.visited = 1; } } } // 左子樹沒有被訪問 如果左孩子不爲空則壓棧 while (curItem.visited == 0) { Node item = curItem.left ; if(item != null) { nodeStack.push(item); curItem = item ; }else { break; } } } int size = nodeList.size(); Node[] result = new Node[size]; nodeList.toArray(result); return result; } public static void print(Node[] result){ for(Node node:result){ System.out.println(node.val); } } } class Node { public int visited = 0 ; // 標識左子樹是否被訪問 public int val ; public Node(int val) { this.val = val; } public int getVal() { return val; } public Node left; public Node right; }