160. 相交链表
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pA = headA;
ListNode pB = headB;
// 双指针
while(pA != pB) {
if (pA == null) pA = headB;
else pA = pA.next;
if (pB == null) pB = headA;
else pB = pB.next;
}
return pA;
}
}

如果两个链表有相交的话,可以拆分成a\b\c三段,然后初始化两个指针分别遍历两个链表,遍历完当前链表就跳到另外一个链表
那么就有结论:两指针按照上面的方式遍历,最后一定会相交于相交点或是null
可能会有人有疑惑就是,你这里判断pA != pB就进行遍历,那么要是前面的a和b部分一样长,会不会最后两指针在null相遇,错过相交点?
其实不会,如果a和b长度相等,那么不需要跳转就能直接找到了,可以模拟一下
236. 二叉树的最近公共祖先
java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// pq都在左子树/都在右子树/分别在左右
return dfs(p, q, root);
}
TreeNode dfs(TreeNode p, TreeNode q, TreeNode curNode) {
if (curNode == null) return null;
if (curNode == p || curNode == q) return curNode;
TreeNode left = dfs(p, q, curNode.left);
TreeNode right = dfs(p, q, curNode.right);
// 不在当前子树
if (right == null && left == null) return null;
// 都在右子树
if (left == null) return right;
// 都在左子树
if (right == null) return left;
// 分别在左右
return curNode;
}
}

这道题比较抽象,对于这类递归类的题目,最好不要去模拟,而是从全局的角度看 ,比如这里为什么是后序遍历,因为对于一个节点是否是最近公共祖先,完全取 决于它的左右子树 中能否找到p和q,所以我们一进来就是判断到当前点是否是p或q中的一个,如果是的话就直接将这个点返回出去,如果不是,就要递归左右子树,并且判断。那么到这里就有四种可能p、q 在当前树的 左子树/右子树/分别在左右/压根不在当前子树,按照情况进行返回就行
234. 回文链表
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
// 找到中点
ListNode slow = head;
ListNode fast = head.next;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 反转
ListNode rev = rev(slow.next);
ListNode p1 = head;
ListNode p2 = rev;
while (p2 != null) {
if (p1.val != p2.val) return false;
p1 = p1.next;
p2 = p2.next;
}
return true;
}
ListNode rev(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
这里使用的思路就是先用快慢指针找到后半段链表的起点,然后对后半段进行反转,然后再用双指针进行遍历
739. 每日温度
java
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
// 单调栈,存储下标
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int n = temperatures.length;
int[] ans = new int[n];
for (int i = 1; i < n; i++) {
while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
int t = stack.pop();
ans[t] = i - t;
}
stack.push(i);
}
return ans;
}
}
这道题可以很明显的看到需要使用单调栈来处理,单调栈能解决的问题其实很有限,主要是用在求最近一个小于/大于当前元素的元素
这里就维护一下单调栈,每次遍历到一个元素大于当前栈顶元素的话,就将栈顶元素出栈,并且确定栈顶元素的下一个大于它的元素所隔的天数