leetcode 数据结构
Created at 2020-04-11 Updated at 2020-07-29 Category 算法 views
数字
7. 整数反转
public int reverse(int x) {
int res = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (res > Integer.MAX_VALUE / 10 || res == Integer.MAX_VALUE / 10 && pop > 7) {
return 0;
}
if (res < Integer.MIN_VALUE / 10 || res == Integer.MIN_VALUE / 10 && pop < -8) {
return 0;
}
res = res * 10 + pop;
}
return res;
}
9. 回文数
public boolean isPalindrome(int x) {
if (x < 0 || x % 10 == 0 && x != 0) {
return false;
}
int rev = 0;
while (x > rev) {
rev = rev * 10 + x % 10;
x = x / 10;
}
return rev == x || x == rev / 10;
}
15. 三数之和
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length < 3) {
return res;
}
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
break;
}
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int l = i + 1, r = nums.length - 1;
while (l < r) {
int sum = nums[l] + nums[r] + nums[i];
if (sum == 0) {
res.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) {
l++;
}
while (l < r && nums[r] == nums[r - 1]) {
r--;
}
l++;
r--;
} else if (sum < 0) {
l++;
} else {
r--;
}
}
}
return res;
}
31. 下一个排列
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
while (i >= 0 && nums[i + 1] <= nums[i]) {
i--;
}
if (i >= 0) {
int j = nums.length - 1;
while (j > i && nums[j] <= nums[i]) {
j--;
}
swap(nums, i, j);
}
reverse(nums, i + 1);
}
private void reverse(int[] nums, int start) {
int i = start, j = nums.length - 1;
while (i < j) {
swap(nums, i, j);
i++;
j--;
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
382. 链表随机节点(蓄水池采样)
class Solution {
public ListNode head;
public Solution(ListNode head) {
this.head = head;
}
public int getRandom() {
int res = head.val;
ListNode node = head.next;
int i = 2;
Random random = new Random();
while (node != null) {
if (random.nextInt(i) == 0) {
res = node.val;
}
i++;
node = node.next;
}
return res;
}
}
398. 随机数索引(蓄水池采样)
class Solution {
public int[] nums;
public Solution(int[] nums) {
this.nums = nums;
}
public int pick(int target) {
Random r = new Random();
int n = 0, index = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target) {
n++;
if (r.nextInt() % n == 0) {
index = i;
}
}
}
return index;
}
}
739. 每日温度
使用单调栈
public int[] dailyTemperatures(int[] T) {
if (T == null || T.length == 0) {
return new int[]{};
}
int[] res = new int[T.length];
Deque<Integer> list = new LinkedList<>();
for (int i = 0; i < T.length; i++) {
while (!list.isEmpty() && T[i] > T[list.peek()]) {
int pre = list.pop();
res[pre] = i - pre;
}
list.push(i);
}
return res;
}
字符串
5. 最长回文子串
中心扩展法
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return "";
}
int start = 0, end = 0;
for (int i = 0; i < s.length() - 1; i++) {
int len1 = helper(s, i, i);
int len2 = helper(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
public int helper(String s, int l, int r) {
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
l--;
r++;
}
return r - l - 1;
}
动态规划
Manacher’s Algorithm
32. 最长有效括号
public int longestValidParentheses(String s)
if (s == null || s.length() == 0) {
return 0;
}
int left = 0, right = 0, max = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left == right) {
max = Math.max(max, right + left)
}
if (right > left) {
left = 0;
right = 0;
}
}
left = 0;
right = 0;
for (int i = s.length() - 1; i >= 0; i--)
if (s.charAt(i) == ')') {
right++;
} else {
left++;
}
if (left == right) {
max = Math.max(max, right + left)
}
if (left > right) {
left = 0;
right = 0;
}
}
return max;
}
678. 有效的括号字符串
public boolean checkValidString(String s) {
if (s == null) {
return false;
}
if (s.length() == 0) {
return true;
}
Deque<Integer> left = new LinkedList<>();
Deque<Integer> star = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
left.push(i);
} else if (c == ')') {
if (left.isEmpty() && star.isEmpty()) {
return false;
}
if (!left.isEmpty()) {
left.pop();
} else {
star.pop();
}
} else {
star.push(i);
}
}
while (!left.isEmpty() && !star.isEmpty()) {
if (left.peek() > star.peek()) {
return false;
}
left.pop();
star.pop();
}
return left.isEmpty();
}
796. 旋转字符串
public boolean rotateString(String A, String B) {
return A.length() == B.length() && (A + A).contains(B);
}
链表
2. 两数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode newHead = new ListNode(0);
ListNode p1 = l1, p2 = l2, curr = newHead;
int carry = 0;
while (p1 != null || p2 != null) {
int x = (p1 != null) ? p1.val : 0;
int y = (p2 != null) ? p2.val : 0;
int sum = x + y + carry;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p1 != null)
p1 = p1.next;
if (p2 != null)
p2 = p2.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return newHead.next;
}
23. 合并K个排序链表
优先队列
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) {
return null;
}
PriorityQueue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>() {
public int compare(ListNode o1, ListNode o2) {
return o1.val - o2.val;
}
});
ListNode dummy = new ListNode(0);
ListNode p = dummy;
for (ListNode node : lists) {
if (node != null) {
queue.add(node);
}
}
while (!queue.isEmpty()) {
ListNode temp = queue.poll();
p.next = temp;
p = p.next;
if (temp.next != null) {
queue.add(temp.next);
}
}
return dummy.next;
}
分治
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) {
return null;
}
return hepler(lists, 0, lists.length - 1);
}
public ListNode hepler(ListNode[] lists, int l, int r) {
if (l == r) {
return lists[l];
}
int m = (l + r) / 2;
ListNode a = hepler(lists, l, m);
ListNode b = hepler(lists, m + 1, r);
return merge(a, b);
}
public ListNode merge(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode head = null;
if (l1.val < l2.val) {
head = l1;
head.next = merge(l1.next, l2);
} else {
head = l2;
head.next = merge(l1, l2.next);
}
return head;
}
25. K 个一组翻转链表
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null) {
return null;
}
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode end = dummy;
while (end.next != null) {
for (int i = 0; i < k && end != null; i++) {
end = end.next;
}
if (end == null) {
break;
}
ListNode start = pre.next;
ListNode next = end.next;
end.next = null;
pre.next = reverse(start);
start.next = next;
pre = start;
end = pre;
}
return dummy.next;
}
public ListNode reverse(ListNode head) {
ListNode pre = null;
while (head != null) {
ListNode next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
86. 分隔链表
public ListNode partition(ListNode head, int x) {
if (head == null) {
return null;
}
ListNode l_head = new ListNode(0);
ListNode r_head = new ListNode(0);
ListNode l = l_head;
ListNode r = r_head;
while (head != null) {
if (head.val < x) {
l.next = head;
l = l.next;
} else {
r.next = head;
r = r.next;
}
head = head.next;
}
// 避免生成环形链表
r.next = null;
l.next = r_head.next;
return l_head.next;
}
146. LRU 缓存机制
基于 LinkedHashMap 实现
import java.util.LinkedHashMap;
import java.util.Map;
public class LRUCache {
private int capacity;
private Map<Integer, Integer> cache;
public LRUCache(int capacity) {
this.capacity = capacity;
this.cache = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
};
}
public int get(int key){
if(cache.containsKey(key)){
return cache.get(key);
}else{
return -1;
}
}
public void put(int key, int value) {
cache.put(key, value);
}
}
基于 HashMap 和双向链表的实现
class LRUCache {
class Node {
Node pre;
Node next;
Integer key;
Integer val;
Node(Integer k, Integer v) {
key = k;
val = v;
}
}
Map<Integer, Node> map = new HashMap<>();
Node head;
Node tail;
Integer capacity;
LRUCache(int capacity) {
this.capacity = capacity;
head = new Node(null, null);
tail = new Node(null, null);
head.next = tail;
tail.pre = head;
}
public int get(int k) {
Node n = map.get(k);
if (n != null) {
remove(n);
add(n);
return n.val;
}
return -1;
}
public void put(int k, int v) {
Node n = map.get(k);
if (n != null) {
n.val = v;
map.put(k, n);
remove(n);
add(n);
} else {
n = new Node(k, v);
add(n);
map.put(k, n);
}
if (map.size() > capacity) {
Node temp = tail.pre;
remove(temp);
map.remove(temp.key);
}
}
private void add(Node n) {
n.pre = head;
n.next = head.next;
head.next.pre = n;
head.next = n;
}
private void remove(Node n) {
n.pre.next = n.next;
n.next.pre = n.pre;
}
}
二叉树
199. 二叉树的右视图
递归
List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
if (root == null) {
return res;
}
helper(root, 0);
return res;
}
public void helper(TreeNode root, int now) {
if (root == null) {
return;
}
if (now == res.size()) {
res.add(root.val);
}
helper(root.right, now + 1);
helper(root.left, now + 1);
}
BFS
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int n = queue.size();
for (int i = 0; i < n; i++) {
TreeNode node = queue.pop();
if (i == n - 1) {
res.add(node.val);
}
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
return res;
}
94. 二叉树的中序遍历
递归
List<Integer> res = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) {
return res;
}
helper(root);
return res;
}
public void helper(TreeNode root) {
if (root == null) {
return;
}
if (root.left != null) {
helper(root.left);
}
res.add(root.val);
if (root.right != null) {
helper(root.right);
}
}
迭代
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<>();
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
return res;
}