面试题22:链表中倒数第k个结点
题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。
public ListNode getKthFromEnd(ListNode head, int k) {
if (head == null || k <= 0) {
return null;
}
ListNode ahead = head;
for (int i = 0; i < k - 1; i++) {
if (ahead.next != null) {
ahead = ahead.next;
} else {
return null;
}
}
ListNode behind = head;
while (ahead.next != null) {
ahead = ahead.next;
behind = behind.next;
}
return behind;
} 面试题23:链表中环的入口结点
题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,环的入口结点是结点3。
- 算法
- 1.使用快慢指针找到环中任一结点
- 2.计算环中结点数量
- 3.以环中结点数量为间距使用前后指针找到环的入口结点
public ListNode entryNodeOfLoop(ListNode head) {
ListNode meetNode = meetNode(head);
if (meetNode == null) {
return null;
}
int nodesInLoop = 1;
ListNode ahead = meetNode;
while (ahead.next != meetNode) {
nodesInLoop++;
ahead = ahead.next;
}
ahead = head;
ListNode behind = head;
for (int i = 0; i < nodesInLoop; i++) {
ahead = ahead.next;
}
while (ahead != behind) {
ahead = ahead.next;
behind = behind.next;
}
return ahead;
}
private ListNode meetNode(ListNode head) {
if (head == null) {
return null;
}
ListNode slow = head.next;
if (slow == null) {
return null;
}
ListNode fast = slow.next;
while (fast != null) {
if (slow == fast) {
return slow;
}
slow = slow.next;
fast = fast.next;
if (fast != null) {
fast = fast.next;
}
}
return null;
} 面试题24:反转链表
题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。
- 算法:
- prev curr after 迭代往后操作
public ListNode reverseList(ListNode head) {
ListNode curr = head;
ListNode prev = null;
while (curr != null) {
ListNode after = curr.next;
curr.next = prev;
prev = curr;
curr = after;
}
return prev;
} 面试题25:合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。例如输入图3.11中的链表1和链表2,则合并之后的升序链表如链表3所示。
- 图3.11
- 链表1:1 -> 3 -> 5
- 链表2:1 -> 2 -> 4
- 链表3:1 -> 1 -> 2 -> 3 -> 4 -> 5
// 迭代
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1);
ListNode move = dummy;
while (true) {
if (l1 == null) {
move.next = l2;
break;
}
if (l2 == null) {
move.next = l1;
break;
}
if (l1.val < l2.val) {
move.next = l1;
l1 = l1.next;
} else {
move.next = l2;
l2 = l2.next;
}
move = move.next;
}
return dummy.next;
}
// 递归
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;
}
} 面试题26:树的子结构
题目:输入两棵二叉树A和B,判断B是不是A的子结构(约定空树不是任意一个树的子结构)。B是A的子结构, 即 A中有出现和B相同的结构和节点值。
public boolean isSubStructure(TreeNode A, TreeNode B) {
if (A != null && B != null) {
if (A.val == B.val) {
if (treeAHasTreeB(A, B)) {
return true;
}
}
return isSubStructure(A.left, B) || isSubStructure(A.right, B);
}
return false;
}
private boolean treeAHasTreeB(TreeNode A, TreeNode B) {
if (B == null) {
return true;
}
if (A == null) {
return false;
}
if (A.val != B.val) {
return false;
}
return treeAHasTreeB(A.left, B.left) && treeAHasTreeB(A.right, B.right);
} 

京公网安备 11010502036488号