年度报告出来了,让我惊讶的是我的勤奋居然能超过98%的扣友(我一直觉得我是很懒的人,难道说很多人只是注册一下就没怎么用过了?)。
文章目录
2021-01-01
1.种花问题(每日一题)
法1:首尾哨兵
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int count = 0;
int m = flowerbed.length;
int[] nums = new int[m + 2];
System.arraycopy(flowerbed, 0, nums, 1, m);
for (int i = 1; i < m + 1; i++) {
if (nums[i - 1] == 0 && nums[i] == 0 && nums[i + 1] == 0) {
nums[i] = 1;
n--;
}
}
return n <= 0;
}
2020-01-02
1.滑动窗口最大值(每日一题)
暴力法能很顺畅写下来,不过应该会超时的。
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length - k + 1;
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
ans[i] = getMaxVaule(Arrays.copyOfRange(nums, i, i + k));
}
return ans;
}
public int getMaxVaule(int[] window) {
int ret = Integer.MIN_VALUE;
for (int i = 0; i < window.length; i++) {
ret = Math.max(ret, window[i]);
}
return ret;
}
维护一个下标对应元素严格单调递减的双端队列。
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length < 2) {
return nums;
}
Deque<Integer> deque = new LinkedList<>();
int[] ans = new int[nums.length - k + 1];
for (int i = 0; i < nums.length; i++) {
while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
deque.pollLast();
}
deque.offerLast(i);
if (deque.peekFirst() + k <= i) {
deque.pollFirst();
}
if (i + 1 - k >= 0) {
ans[i + 1 - k] = nums[deque.peekFirst()];
}
}
return ans;
}
2020-01-03
1.分隔链表(每日一题)
public ListNode partition(ListNode head, int x) {
ListNode dummy1 = new ListNode(-1);
ListNode cur1 = dummy1;
ListNode dummy2 = new ListNode(-1);
ListNode cur2 = dummy2;
while (head != null) {
if (head.val < x) {
cur1.next = new ListNode(head.val);
cur1 = cur1.next;
} else {
cur2.next = new ListNode(head.val);
cur2 = cur2.next;
}
head = head.next;
}
cur1.next = dummy2.next;
return dummy1.next;
}
2.两两交换链表中的节点
法1:递归
public ListNode swapPairs(ListNode head) {
if (head == null) {
return null;
}
if (head.next == null) {
return head;
}
ListNode node = head.next;
head.next = swapPairs(node.next);
node.next = head;
return node;
}
2020-01-04
1.斐波那契数
public int fib(int n) {
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
2020-01-05
1.较大分组的位置(每日一题)
public List<List<Integer>> largeGroupPositions(String s) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
int i = 0;
// 尾哨兵
String str = s + " ";
char[] ca = str.toCharArray();
for (int j = 1; j < ca.length; j++) {
if (ca[j] != ca[i]) {
if (j - i >= 3) {
// List<Integer> list = new ArrayList<>();
// list.add(i);
// list.add(j - 1);
// ans.add(list);
ans.add(Arrays.asList(i, j - 1));
}
i = j;
}
}
return ans;
}
2020-01-07
1.省份数量(每日一题)
public int findCircleNum(int[][] isConnected) {
int n = isConnected.length;
boolean[] visited = new boolean[n];
int ans = 0;
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (visited[i]) {
continue;
}
queue.offer(i);
visited[i] = true;
ans++;
while (!queue.isEmpty()) {
int cur = queue.poll();
for (int j = 0; j < n; j++) {
if (isConnected[cur][j] == 1 && !visited[j]) {
queue.offer(j);
visited[j] = true;
}
}
}
}
return ans;
}
2020-01-08
1.旋转数组
dy网络的面试题
法1:
public void rotate(int[] nums, int k) {
int n = nums.length;
k %= n;
int[] temp = new int[n];
for (int i = 0; i < n; i++) {
temp[(i + k) % n] = nums[i];
}
for (int i = 0; i < n; i++) {
nums[i] = temp[i];
}
}
2020-03-06
1.下一个更大元素 II(每日一题)
法1:暴力法
// public int[] nextGreaterElements(int[] nums) {
// if (nums.length <= 0) {
// return new int[0];
// }
// int[] ans = new int[nums.length];
// ans[0] = -1;
// for (int i = 0; i < nums.length; i++) {
// boolean flag = false;
// for (int j = i; j < nums.length; j++) {
// if (nums[j] > nums[i]) {
// ans[i] = nums[j];
// flag = true;
// break;
// }
// }
// if (flag) {
// continue;
// }
// for (int j = 0; j < i; j++) {
// if (nums[j] > nums[i]) {
// ans[i] = nums[j];
// break;
// }
// ans[i] = -1;
// }
// }
// return ans;
// }
public int[] nextGreaterElements(int[] nums) {
if (nums.length <= 0) {
return new int[0];
}
int[] ans = new int[nums.length];
ans[0] = -1;
for (int i = 0; i < nums.length; i++) {
ans[i] = -1;
for (int j = i + 1; j < i + nums.length; j++) {
if (nums[j % nums.length] > nums[i]) {
ans[i] = nums[j % nums.length];
break;
}
}
}
return ans;
}
时O(n²)
空O(n)
法2:单调栈
public int[] nextGreaterElements(int[] nums) {
if (nums.length <= 0) {
return new int[0];
}
Deque<Integer> stack = new LinkedList();
int[] ans = new int[nums.length];
Arrays.fill(ans, -1);
for (int i = 0; i < 2 * nums.length; i++) {
int idx = i % nums.length;
while (!stack.isEmpty() && nums[stack.peek()] < nums[idx]) {
ans[stack.pop()] = nums[idx];
}
stack.push(idx);
}
return ans;
}
时O(n)
空O(n)
2021-03-07
1.分割回文串(每日一题)
public List<List<String>> partition(String s) {
int len = s.length();
List<List<String>> res = new ArrayList<>();
if (len == 0) {
return res;
}
Deque<String> stack = new ArrayDeque<>();
char[] charArray = s.toCharArray();
dfs(charArray, 0, len, stack, res);
return res;
}
private void dfs(char[] charArray, int index, int len, Deque<String> path, List<List<String>> res) {
if (index == len) {
res.add(new ArrayList<>(path));
return;
}
for (int i = index; i < len; i++) {
if (!isPalindrome(charArray, index, i)) {
continue;
}
path.addLast(new String(charArray, index, i + 1 - index));
dfs(charArray, i + 1, len, path, res);
path.removeLast();
}
}
private boolean isPalindrome(char[] charArray, int left, int right) {
while (left < right) {
if (charArray[left] != charArray[right]) {
return false;
}
left++;
right--;
}
return true;
}
2.全排列
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList();
List<Integer> list = new ArrayList();
if (nums.length == 0) {
return res;
}
boolean[] visited = new boolean[nums.length];
dfs(nums, 0, list, visited, res);
return res;
}
private void dfs(int[] nums,int depth, List<Integer> list, boolean[] visited, List<List<Integer>> res) {
if (depth == nums.length) {
res.add(new ArrayList<>(list));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!visited[i]) {
list.add(nums[i]);
visited[i] = true;
dfs(nums,depth + 1, list, visited, res);
visited[i] = false;
list.remove(depth);
}
}
}
2021-03-09
1.删除字符串中的所有相邻重复项
法1:快慢指针
public String removeDuplicates(String S) {
char[] chars = S.toCharArray();
int j = -1;
for (int i = 0; i < chars.length; i++) {
if (j != -1 && chars[i] == chars[j]) {
j--;
} else {
chars[++j] = chars[i];
}
}
return new String(chars).substring(0, j + 1);
}
时O(n)
空O(n)
2020-03-10
1.第一个错误的版本
public int firstBadVersion(int n) {
int l = 1;
int h = n;
while (l <= h) {
int mid = l + (h - l) / 2;
if (isBadVersion(mid)) {
h = mid - 1;
} else {
l = mid + 1;
}
}
return l;
}
时O(logn)
空O(1)
2.基本计算器(每日一题)
public int calculate(String s) {
Deque<Integer> stack = new ArrayDeque<Integer>();
char[] chars = s.replace(" ", "").toCharArray();
int sign = 1;
stack.push(sign);
int ans = 0;
int i = 0;
while (i < chars.length) {
if (chars[i] == '+') {
sign = stack.peek();
i++;
} else if (chars[i] == '-') {
sign = -stack.peek();
i++;
} else if (chars[i] == '(') {
stack.push(sign);
i++;
} else if (chars[i] == ')') {
stack.pop();
i++;
} else {
int num = 0;
while (i < chars.length && chars[i] >= '0' && chars[i] <= '9') {
num = num * 10 + chars[i] - '0';
i++;
}
ans += sign * num;
}
}
return ans;
}
时,空O(n)
3.验证回文字符串 Ⅱ
public boolean validPalindrome(String s) {
int l = 0, h = s.length() - 1;
while (l < h) {
if (s.charAt(l) == s.charAt(h)) {
l++;
h--;
} else {
return validPalindrome(s, l + 1, h) || validPalindrome(s, l, h - 1);
}
}
return true;
}
private boolean validPalindrome(String s, int i, int j) {
while (i < j) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
i++;
j--;
}
return true;
}
vivo第二题:把返回true改成返回字符串。
public String validPalindrome(String s) {
int l = 0, h = s.length() - 1;
while (l < h) {
if (s.charAt(l) == s.charAt(h)) {
l++;
h--;
} else if (validPalindrome(s, l + 1, h)) {
return String.valueOf(new StringBuffer(s).deleteCharAt(l));
} else if (validPalindrome(s, l, h - 1)) {
return String.valueOf(new StringBuffer(s).deleteCharAt(h));
} else {
return "false";
}
}
return s;
}
private boolean validPalindrome(String s, int i, int j) {
while (i < j) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
i++;
j--;
}
return true;
}
2021-03-11
1.课程表
public boolean canFinish(int numCourses, int[][] prerequisites) {
int[] indegrees = new int[numCourses]; // 入度表
int cnt = 0;
List<List<Integer>> adj = new ArrayList();
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
adj.add(new ArrayList());
}
for (int[] p : prerequisites) {
indegrees[p[0]]++;
adj.get(p[1]).add(p[0]);
}
for (int i = 0; i < numCourses; i++) {
if (indegrees[i] == 0) {
queue.add(i);
}
}
while (!queue.isEmpty()) {
int pre = queue.poll();
cnt++;
for (int cur : adj.get(pre)) {
if (--indegrees[cur] == 0) {
queue.add(cur);
}
}
}
return numCourses == cnt;
}
时O(N+M)
空O(N+M)
2.课程表 II
public int[] findOrder(int numCourses, int[][] prerequisites) {
int[] indegrees = new int[numCourses]; // 入度表
List<Integer> res = new ArrayList();
List<List<Integer>> adj = new ArrayList();
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
adj.add(new ArrayList());
}
for (int[] p : prerequisites) {
indegrees[p[0]]++;
adj.get(p[1]).add(p[0]);
}
for (int i = 0; i < numCourses; i++) {
if (indegrees[i] == 0) {
queue.add(i);
}
}
while (!queue.isEmpty()) {
int pre = queue.poll();
res.add(pre);
for (int cur : adj.get(pre)) {
if (--indegrees[cur] == 0) {
queue.add(cur);
}
}
}
if (res.size() != numCourses) {
return new int[0];
}
int[] ans = new int[res.size()];
for (int i = 0; i < res.size(); i++) {
ans[i] = res.get(i);
}
return ans;
}
3.平方数之和
public boolean judgeSquareSum(int c) {
int l = 0, h = (int) Math.sqrt(c);
while (l <= h) {
int sum = l * l + h * h;
if (sum == c) {
return true;
} else if (sum > c) {
h--;
} else {
l++;
}
}
return false;
}
4.前 K 个高频元素
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
int[] res = new int[k];
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
List<Integer>[] list = new ArrayList[nums.length + 1];
for (int num : map.keySet()) {
int i = map.get(num);
if (list[i] == null) {
list[i] = new ArrayList<>();
}
list[i].add(num);
}
int i = 0, t, j;
// 从频次最高的第一个不为空null的桶开始反向取值
for (t = nums.length; t > 0; t--) {
if (list[t] != null) {
for (j = 0; j < list[t].size() && i < k; j++) {
res[i++] = list[t].get(j);
}
}
}
return res;
}
O(n)
2021-03-12
1.根据字符出现频率排序
public String frequencySort(String s) {
HashMap<Character, Integer> hashMap = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
hashMap.put(s.charAt(i), hashMap.getOrDefault(s.charAt(i), 0) + 1);
}
List<Character>[] buckets = new ArrayList[s.length() + 1];
for (char ch : hashMap.keySet()) {
int cnt = hashMap.get(ch);
if (buckets[cnt] == null) {
buckets[cnt] = new ArrayList<>();
}
buckets[cnt].add(ch);
}
char[] res = new char[s.length()];
int i = 0;
for (int k = s.length(); k > 0; k--) {
if (buckets[k] != null) {
for (char ch : buckets[k]) {
for (int j = 0; j < k; j++) {
res[i++] = ch;
}
}
}
}
return String.valueOf(res);
}
2.连续的子数组和
法1:
public boolean checkSubarraySum(int[] nums, int k) {
for (int i = 0; i < nums.length; i++) {
int sum = 0;
for (int j = i; j < nums.length; j++) {
sum += nums[j];
if (j - i > 0) {
if (k == 0 && sum == 0 || (k != 0 && sum % k == 0)) {
return true;
}
}
}
}
return false;
}
O(n平方),O(1)
法2:
public boolean checkSubarraySum(int[] nums, int k) {
int sum = 0;
Map<Integer, Integer> map = new HashMap<>(); // key:preSum % k, value:索引
map.put(0, -1);
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
int temp = k == 0 ? sum : sum % k;
if(map.containsKey(temp)) {
if(i - map.get(temp) > 1) {
return true;
}
continue;
}
map.put(temp, i);
}
return false;
}
O(n),空间换时间。
3.根据身高重建队列
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]);
List<int[]> res = new ArrayList<>();
for (int[] p : people) {
res.add(p[1], p);
}
return res.toArray(new int[res.size()][2]);
}
2021-03-13
1.用最少数量的箭引爆气球
public int findMinArrowShots(int[][] points) {
if (points.length == 0) {
return 0;
}
Arrays.sort(points, (p1, p2) -> p1[1] < p2[1] ? -1 : 1);
int cnt = 1;
int end = points[0][1];
for (int i = 1; i < points.length; i++) {
if (points[i][0] <= end) {
continue;
}
cnt++;
end = points[i][1];
}
return cnt;
}
闲谈
大年初一陪家里人去风力电站游玩,大自然和音乐给我带来了很大的愉悦。
风车、落日、微风、松树、红花荷、烟花……多么美好且难忘的一天。
那天,舒曼的《花纹》在山顶上缓缓响起,从傍晚到夜晚。