面试题目的最优解,确定最优解
有区分度的题目 》 考的万无一失的题目;高频题目
在痛苦就听下去,
【面试】锻炼一种能力,絮絮叨叨的把想法想出来,完成思路的碰撞。从人性出发,絮絮叨叨弄出来,面试官:“我帮你一下”,絮絮叨叨又不要招人烦。牛逼啊,太牛逼了。
链表结构:
给定一个 Node 结构:
public static class Node { public int value; public Node next; public Node(int data) { this.value = data; } }
1) 单链表和双链表如何反转
1.1 单向链表
这是一个单链表结构, 假设初始时,a --> b --> c --> null :
那么如何实现指针的反转,最终 c --> b --> a --> null ?
代码实现:
public static Node reverseLinkedList(Node head) { Node pre = null; Node next = null; while (head != null) { // 保存好下一个结点要用的head 的指针,不然就不知道一会应该操作谁了。 next = head.next; // 改变当前 head 的指针,使其指向 pre,指回去 head.next = pre; // 把pre存好给下一个用,不然下一个就不知道指向哪里了。 pre = head; // 把 next 下一次循环的 head head = next; } // 返回pre 元素,就是返回头节点。 return pre; }
1.2 双向链表
public class LinkedListTest2 { public static Node[] nodes = new Node[3]; static { Node a = new Node(1); Node b = new Node(2); Node c = new Node(3); a.prev = null; a.next = b; b.prev = a; b.next = c; c.prev = b; c.next = null; nodes[0] = a; nodes[1] = b; nodes[2] = c; } public static void main(String[] args) { Node head = nodes[0]; printNodes(head); Node newHead = reverseLinkedList(head); System.out.println("\n反转后:"); printNodes(newHead); } public static void printNodes(Node head) { while (head != null) { System.out.println(head.prev + " <-- " + head.value + " --> " + head.next); head = head.next; } } public static class Node { public Node prev; public int value; public Node next; public Node(int value) { this.value = value; } public String toString() { return Integer.valueOf(value).toString(); } } /** * prev --> head --> next */ public static Node reverseLinkedList(Node head) { Node prev = null; Node next = null; while (head != null) { next = head.next; prev = head.prev; head.prev = next; head.next = prev; prev = head; head = next; } return prev; } }
2) 把给定值都删除
/** * 2 -> 2-> 3-> 2-> 3-> 4 * 若:删除 num = 3,得到: * 2 -> 2-> 2-> 4,return head = 2 * 若:删除 num = 2 得到: * 3-> 3-> 4 ,return head= 3 * @param head * @param val * @return */ public static ListNode removeValue(ListNode head, int val) { // head 来到第一个不需要删除的位置 while(head != null) { if (head.val != val) { break; } head = head.next; } // 1、head == null 表示所有 node 都是 num,return null // 2、head != null ListNode prev = head; ListNode curr = head; while (curr != null) { if (curr.val == val) prev.next = curr.next; else prev = curr; curr = curr.next; } return head; }
1.3 java内存泄漏:
Java使用的是可达性算法,对于不可达对象会随时释放(自动释放内存
2. 栈和队列的实际实现:
栈:数据先进后出,犹如弹匣
队列:数据先进先出,好似排队
2.1 双向链表 (对栈和队列)的实现:
保留头进和头出
保留头进和尾出
双向链表
public static class Node<T> {<!-- --> public T value; public Node<T> last; public Node<T> next; public Node(T data) {<!-- --> value = data; } } //双向链表 public static class DoubleEndsQueue<T> {<!-- --> public Node<T> head; public Node<T> tail; public void addFromHead(T value) {<!-- --> Node<T> cur = new Node<T>(value); if (head == null) {<!-- --> head = cur; tail = cur; } else {<!-- --> cur.next = head; head.last = cur; head = cur; } } public void addFromBottom(T value) {<!-- --> Node<T> cur = new Node<T>(value); if (head == null) {<!-- --> head = cur; tail = cur; } else {<!-- --> cur.last = tail; tail.next = cur; tail = cur; } } public T popFromHead() {<!-- --> if (head == null) {<!-- --> return null; } Node<T> cur = head; if (head == tail) {<!-- --> head = null; tail = null; } else {<!-- --> head = head.next; cur.next = null; head.last = null; } return cur.value; } public T popFromBottom() {<!-- --> if (head == null) {<!-- --> return null; } Node<T> cur = tail; if (head == tail) {<!-- --> head = null; tail = null; } else {<!-- --> tail = tail.last; tail.next = null; cur.last = null; } return cur.value; } public boolean isEmpty() {<!-- --> return head == null; } }
栈
public static class MyStack { private DoubleEndsQueue< public MyStack() { queue = new DoubleEndsQueue(); } public void push(T value) { queue.addFromHead(value); } public T pop() { return queue.popFromHead(); } public boolean isEmpty() { return queue.isEmpty(); } }
队列
public static class MyQueue { private DoubleEndsQueue queue; public MyQueue() { queue = new DoubleEndsQueue(); } public void push(T value) { queue.addFromHead(value); } public T poll() { return queue.popFromBottom(); } public boolean isEmpty() { return queue.isEmpty(); } }
2.2 数组实现
面试中是动态实现的
语言的api的有限的,手动改写是不确定的。
两个栈拼队列来搞、两个队列拼栈来搞。