不善言谈的优秀程序员在面试中每每是要吃巨亏的,你没有办法经过说话来轻易证实本身的实力。不管是大厂仍是小厂,大部分面试官都不具有优秀的面试能力,它们也只能经过三言两语观察一下面试者的表面工夫。有不少这样吃了亏的程序员,不喜欢准备面试,不喜欢吹嘘虚假的不存在的经验和能力,甚至连网上的笔试题都懒得作,由于在实际工做中这些鸟题根本一点都用不上。java
可是这并非什么值得骄傲的真诚,面试不作准备是对目标企业的不尊重,也是我的性格上自大的一种表现。虽然全部的面试官都但愿面试者是真实的无虚假的不作表面文章的,可是这样的人真的站在你面前时,几乎全部的面试官每每又都看不上。程序员
那如何在尽可能少作表面功夫的基础上让面试官可以看上你?其中的方法之一就是展示平时我的优秀的做品和实现代码,可是这须要时间须要实打实的功夫,可以有机会做出优秀我的做品的人并很少见,大多数人都在忙碌的工做中耗尽了全部的时间。那还有一个方法就是在笔试阶段大显身手,让本身优秀的代码能力跃然纸上,让面试官瞬间对你产生不同的感受。面试
不要被笔试阶段那些算法题给吼到了,在你眼里彷佛它们是为程序天才们准备的。其实大多数公司的笔试题也是来源于网上,那些被无数人作烂的题目。你被题目搞晕了而别人没有,那是由于别人已经作过这道题了,而不是智商所致。算法
就拿今天我要讲的算法题 —— 逆转单向链表,它是一个很是简单的题目,可是若是你是第一次见到这道题,将它完完整整没有 bug 的写出来是着实须要费一番功夫的。指望在那短短的笔试题环节就轻松搞定这道题,那真是很是有算法天赋的人才能作到的事。难道大厂里面的程序员个个都是天才,鬼才相信。天才老是极少数的,多数都是像老钱这样的庸才。app
好,言归正传,下面咱们开始讲解今天的算法题 —— 逆转单向链表。首先这是一个单向的链表,不一样于 Java 里面的 LinkedList,它是双向的链表。链表中每一个节点之间经过 next 指针串接起来,会有一个链表头和链表尾指针 hold 住整个链表。逆转的任务就是将 head -> a -> b -> c -> d <- tail 变成 head -> d -> c -> b -> a <- tail。oop
class Node<T> {
T value;
Node<T> next;
Node(T value) {
this.value = value;
}
}
class ReverseLinkedList<T> {
Node<T> head, tail;
}
复制代码
咱们须要将全部的元素一个一个的使用 next 指针串接起来,链表的头尾节点要用 head 和 tail 变量把持住。加入新元素时,须要调整尾部节点的 next 指针,指向新加入的元素节点。 ui
class ReverseLinkedList<T> {
private Node<T> head, tail;
public ReverseLinkedList(T... values) {
for (T value : values) {
if (tail == null) {
// 第一个节点
head = tail = new Node<>(value);
} else {
// 后面的节点往链表尾部追加
Node<T> oldTail = tail;
oldTail.next = tail = new Node<>(value);
}
}
}
}
ReverseLinkedList<Integer> l = new ReverseLinkedList<>(1,2,3,4,5,6);
复制代码
咱们须要提供一个链表的输出方法,以便快速对比逆转后链表的内容是否正确 this
class ReverseLinkedList<T> {
private Node<T> head, tail;
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
Node<T> cur = head;
while (cur != null) {
sb.append(cur.value);
cur = cur.next;
if (cur != null) {
sb.append(',');
}
}
sb.append(']');
return sb.toString();
}
}
复制代码
循环调整 next 指针是最容易想到的方法,可是要将指针精确地逆转正确其实并不容易。下面代码中的循环部分很短,可是却很精致,使用了三个临时局部变量 cur、next 和 nextnext,稍有不慎就会出错。 spa
class ReverseLinkedList<T> {
private Node<T> head, tail public ReverseLinkedList<T> reverseByLoop() {
// 空链表或者单元素都无需处理
if (head == tail) {
return this;
}
Node<T> cur = head;
Node<T> next = cur.next;
while (next != null) {
Node<T> nextnext = next.next;
next.next = cur;
cur = next;
next = nextnext;
}
tail = head;
tail.next = null;
head = cur;
return this;
}
}
复制代码
使用递归的思想来解决这个问题也是一个很好的主意,只不过当链表特别长时,调用栈会很深,链表长到必定程度就会抛出臭名昭著的异常 StackOverflowException。 3d
class ReverseLinkedList<T> {
private Node<T> head, tail public ReverseLinkedList<T> reverseByRecursive() {
Node<T> oldTail = tail;
tail = reverseFrom(head);
tail.next = null;
head = oldTail;
return this;
}
private Node<T> reverseFrom(Node<T> from) {
if (from == tail) {
return from;
}
Node<T> end = reverseFrom(from.next);
end.next = from;
return from;
}
}
复制代码
package leetcode;
public class ReverseLinkedList<T> {
static class Node<T> {
T value;
Node<T> next;
Node(T value) {
this.value = value;
}
}
Node<T> head;
Node<T> tail;
@SafeVarargs
public ReverseLinkedList(T... values) {
for (T value : values) {
if (tail == null) {
head = tail = forNode(value);
} else {
Node<T> oldTail = tail;
oldTail.next = tail = forNode(value);
}
}
}
public ReverseLinkedList<T> reverseByLoop() {
if (head == tail) {
return this;
}
Node<T> cur = head;
Node<T> next = cur.next;
while (next != null) {
Node<T> nextnext = next.next;
next.next = cur;
cur = next;
next = nextnext;
}
tail = head;
tail.next = null;
head = cur;
return this;
}
public ReverseLinkedList<T> reverseByRecursive() {
Node<T> oldTail = tail;
tail = reverseFrom(head);
tail.next = null;
head = oldTail;
return this;
}
private Node<T> reverseFrom(Node<T> from) {
if (from == tail) {
return from;
}
Node<T> end = reverseFrom(from.next);
end.next = from;
return from;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
Node<T> cur = head;
while (cur != null) {
sb.append(cur.value);
cur = cur.next;
if (cur != null) {
sb.append(',');
}
}
sb.append(']');
return sb.toString();
}
private static <T> Node<T> forNode(T value) {
return new Node<>(value);
}
public static void main(String[] args) {
ReverseLinkedList<Integer> rl = new ReverseLinkedList<>(1, 2, 3, 4, 5, 6);
System.out.println(rl.reverseByRecursive().reverseByRecursive());
}
}
复制代码