剑指 Offer 30. 包含min函数的栈 2022.7.26
class MinStack {
Stack<Integer> sk = new Stack<>();
Stack<Integer> minStack = new Stack<>();
/** initialize your data structure here. */
public MinStack() {
}
public void push(int x) {
if (minStack.isEmpty() || x <= minStack.peek()) {
minStack.push(x);
}
sk.push(x);
}
public void pop() {
if (minStack.peek().equals(sk.peek())) {
minStack.pop();
}
sk.pop();
}
public int top() {
return sk.peek();
}
public int min() {
return minStack.peek();
}
}
剑指 Offer 38. 字符串的排列 2022.7.26
class Solution {
public String[] permutation(String s) {
permutaUnique(s.toCharArray());
String[] arr = new String[res.size()];
for (int i = 0; i < res.size(); i++) {
arr[i] = res.get(i);
}
return arr;
}
List<String> res = new LinkedList<>();
boolean[] used;
StringBuilder track = new StringBuilder();
public List<String> permutaUnique(char[] nums) {
Arrays.sort(nums);
used = new boolean[nums.length];
backtrack(nums);
return res;
}
void backtrack(char[] nums) {
if (track.length() == nums.length) {
res.add(track.toString());
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i] == true) {
continue;
}
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
continue;
}
track.append(nums[i]);
used[i] = true;
backtrack(nums);
track.deleteCharAt(track.length() - 1);
used[i] = false;
}
}
}
剑指 Offer 36. 二叉搜索树与双向链表 2022.7.26
class Solution {
Node pre, head;
public Node treeToDoublyList(Node root) {
if (root == null) {
return null;
}
traverse(root);
head.left = pre;
pre.right = head;
return head;
}
void traverse(Node root) {
if (root == null) {
return;
}
traverse(root.left);
if (pre == null) {
head = root;
} else {
pre.right = root;
root.left = pre;
}
pre = root;
traverse(root.right);
}
}
剑指 Offer 53 - II. 0~n-1中缺失的数字 2022.7.26
力扣算法 Java 刷题笔记【数组篇 二分搜索】hot100(一)二分查找、搜索插入位置、在排序数组中查找元素的第一个和最后一个位置 3
class Solution {
public int missingNumber(int[] nums) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] > mid) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
}
剑指 Offer 11. 旋转数组的最小数字 2022.7.26
class Solution {
public int minArray(int[] numbers) {
int l = 0, r = numbers.length - 1;
while (l < r) {
if (numbers[l] < numbers[r]) {
return numbers[l];
}
int mid = l + (r - l) / 2;
if (numbers[mid] > numbers[l]) {
l = mid + 1;
} else if (numbers[mid] < numbers[l]) {
r = mid;
} else {
l++;
}
}
return numbers[l];
}
}
剑指 Offer 65. 不用加减乘除做加法 2022.7.27
class Solution {
public int add(int a, int b) {
if(a == 0 || b == 0) {
return a == 0 ? b : a;
}
// 设 a = 1001
// 设 b = 0101
// 求和 1100
int sum = a ^ b;
// 进位 0001 << 1 = 0010
int carry = (a & b) << 1;
// add(1100, 0010)
return add(sum, carry);
}
}
剑指 Offer 14- I. 剪绳子 2022.7.28
class Solution {
public int cuttingRope(int n) {
if (n <= 2) {
return 1;
}
if (n == 3) {
return 2;
}
if (n == 4) {
return 4;
}
int res = n / 3;
int mod = n % 3;
if (n % 3 == 0) {
return (int)Math.pow(3, res);
} else if (n % 3 == 1) {
return (int)(Math.pow(3, res - 1) * 4);
} else {
return (int)(Math.pow(3, res) * 2);
}
}
}
剑指 Offer 14- II. 剪绳子 II 2022.7.28
class Solution {
public int cuttingRope(int n) {
if (n < 4) {
return n - 1;
}
int res = n / 3;
int mod = n % 3;
int p = 1000000007;
if (mod == 0) {
return (int)(pow(3, res));
} else if (mod == 1) {
return (int)(pow(3, res - 1) * 4 % p);
} else {
return (int)(pow(3, res) * 2 % p);
}
}
long pow (int a, int n) {
long sum = 1;
int p = 1000000007;
for (int i = 0; i < n; i++) {
sum = sum * a % p;
}
return sum;
}
}
剑指 Offer 33. 二叉搜索树的后序遍历序列 2022.7.28
class Solution {
public boolean verifyPostorder(int[] postorder) {
return verify(postorder, 0, postorder.length - 1);
}
boolean verify(int[] postorder, int start, int end) {
if (start >= end) {
return true;
}
int p = start;
while (postorder[p] < postorder[end]) {
p++;
}
int m = p;
while (postorder[m] > postorder[end]) {
m++;
}
return m == end && verify(postorder, start, p - 1) && verify(postorder, p, m - 1);
}
}
剑指 Offer 50. 第一个只出现一次的字符 2022.7.28
class Solution {
public char firstUniqChar(String s) {
int[] nums = new int[26];
for (int i = 0; i < s.length(); i++) {
nums[s.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (nums[c - 'a'] == 1) {
return c;
}
}
return ' ';
}
}
剑指 Offer 34. 二叉树中和为某一值的路径 2022.7.28
class Solution {
List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
if (root == null) {
return res;
}
dfs(root, target, new LinkedList<>());
return res;
}
void dfs(TreeNode root, int sum, LinkedList<Integer> path) {
if (root == null) {
return;
}
sum = sum - root.val;
if (root.left == null && root.right == null) {
if (sum == 0) {
path.addLast(root.val);
res.add(new LinkedList<>(path));
path.removeLast();
}
return;
}
path.addLast(root.val);
dfs(root.left, sum, path);
path.removeLast();
path.addLast(root.val);
dfs(root.right, sum, path);
path.removeLast();
}
}
剑指 Offer 53 - I. 在排序数组中查找数字 I 2022.7.29
力扣算法 Java 刷题笔记【数组篇 二分搜索】hot100(一)二分查找、搜索插入位置、在排序数组中查找元素的第一个和最后一个位置 3
class Solution {
public int search(int[] nums, int target) {
int left_index = left_bound(nums, target);
if (left_index == -1) {
return 0;
}
int right_index = right_bound(nums, target);
return right_index - left_index + 1;
}
int left_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
right = mid - 1;
}
}
if (left >= nums.length || nums[left] != target) {
return -1;
}
return left;
}
int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
left = mid + 1;
}
}
if (right < 0 || nums[right] != target) {
return -1;
}
return right;
}
}
剑指 Offer 40. 最小的k个数 2022.7.29
方法一:优先队列
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0 || arr.length == 0) {
return new int[0];
}
PriorityQueue<Integer> pq = new PriorityQueue<>();
int[] res = new int[k];
int i = 0;
for (int a : arr) {
pq.offer(a);
if (pq.size() > arr.length - k) {
res[i] = pq.poll();
i++;
}
}
return res;
}
}
******** 另一种写法
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if (k == 0 || arr.length == 0) {
return new int[0];
}
// 默认是小根堆,实现大根堆需要重写一下比较器。
Queue<Integer> pq = new PriorityQueue<>((v1, v2) -> v2 - v1);
for (int num: arr) {
if (pq.size() < k) {
pq.offer(num);
} else if (num < pq.peek()) {
pq.poll();
pq.offer(num);
}
}
int[] res = new int[pq.size()];
int idx = 0;
for(int num: pq) {
res[idx++] = num;
}
return res;
}
}
方法二:快排
剑指 Offer 39. 数组中出现次数超过一半的数字 2022.7.29
摩尔投票法(对拼消耗)
class Solution {
public int majorityElement(int[] nums) {
int count = 0;
int candicate = 0;
for (int num : nums) {
if (count == 0) {
candicate = num;
}
count += candicate == num ? 1 : -1;
}
return candicate;
}
}