思路1:
两个循环从后面找小于等于当前数的,找到就结束内循环
public int[] finalPrices(int[] prices) {
for (int i = 0; i < prices.length; i++) {
for (int j = i + 1; j < prices.length; j++) {
if (prices[i] >= prices[j]) {
prices[i] = prices[i] - prices[j];
break;
}
}
}
return prices;
}
思路2:
要找每个元素的下一个小于等于它的元素,可以用单调栈,维护一个单调递增的栈,栈存储元素下标,当前元素比栈顶元素小表示栈顶元素找到了下一个小于等于它的元素,栈里面的元素都是没找到小于等于自己的元素的。当出现一个比栈顶小的元素时,我们根据大小不停地弹出栈顶当前元素就是小于等于该栈顶的第一个数了
public int[] finalPrices(int[] prices) {
Deque<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < prices.length; i++) {
// 当前元素比栈顶元素小,栈顶元素就出栈,直到当前元素比栈顶元素大
while (!queue.isEmpty() && prices[i] <= prices[queue.peek()]) {
Integer pop = queue.pop();
// 当前元素比栈顶元素小表示栈顶元素找到了一个有折扣的元素
prices[pop] = prices[pop] - prices[i];
}
queue.push(i);
}
return prices;
}
思路:
使用后序遍历记录每个节点的最大相同路径长度,有可能是自己加左子树,有可能是自己加右子树,有可能是自己加左右子树,
同时刷新全局的最大值
int max = 0;
public int longestUnivaluePath(TreeNode root) {
longestUnivaluePathDfs(root);
return max;
}
public int longestUnivaluePathDfs(TreeNode root) {
if (root == null) {
return 0;
}
int leftVal = longestUnivaluePathDfs(root.left);
int rightVal = longestUnivaluePathDfs(root.right);
int leftVal1 = 0, rightVal1 = 0;
// 当前节点和左子树的节点的值一样大,自己加左子树
if (root.left != null && root.left.val == root.val) {
leftVal1 = leftVal + 1;
}
// 当前节点和右子树的节点的值一样大,自己加右子树
if (root.right != null && root.right.val == root.val) {
rightVal1 = rightVal + 1;
}
// 自己加左右子树
max = Math.max(max, leftVal1 + rightVal1);
return Math.max(leftVal1, rightVal1);
}
思路:
使用序列化序列化每一个节点,然后用哈希表记录这个节点的序列化是否出现过,出现过就把这个节点加入到结果里
// key是节点序列化后的结果,val是节点
Map<String, TreeNode> seen = new HashMap<>();
List<TreeNode> duplicate = new ArrayList<>();
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
findDuplicateSubtrees(root);
return duplicate;
}
public String findDuplicateSubtreesDfs(TreeNode root) {
if (root == null) {
return "";
}
StringBuilder sb = new StringBuilder();
sb.append(root.val);
sb.append("(").append(findDuplicateSubtreesDfs(root.left)).append(")(").append(findDuplicateSubtreesDfs(root.right)).append(")");
String key = sb.toString();
// 出现过
if (seen.containsKey(key)) {
duplicate.add(seen.get(key));
} else {
seen.put(key, root);
}
return key;
}
2022.9.7
思路:
直接模拟,统计单词数和空格数,最后计算每个单词之间相隔多少个空格,最后拼接
public String reorderSpaces(String text) {
char[] chars = text.toCharArray();
int spaceCount = 0, wordCount = 0;
for (int i = 0; i < chars.length; i++) {
// 统计单词数
if ((i == 0 && chars[i] != ' ') || (i > 0 && (chars[i-1] == ' ') && chars[i] != ' ')) {
wordCount++;
}
// 统计空格数
if (chars[i] == ' ') {
spaceCount++;
}
}
StringBuilder sb = new StringBuilder();
if (wordCount == 1 && spaceCount == 0) {
return text.trim();
}
if (wordCount == 1 && spaceCount != 0) {
sb = new StringBuilder();
sb.append(text.trim());
for (int j = 0; j < spaceCount; j++) {
sb.append(" ");
}
return sb.toString();
}
String[] s = text.split(" ");
int count = spaceCount / (wordCount - 1);
for (int i = 0; i < s.length; i++) {
if (!"".equals(s[i])) {
sb.append(s[i]);
wordCount--;
// 单词添加完了看还有没有剩余的空格要添加
if (wordCount == 0) {
while (spaceCount != 0) {
sb.append(" ");
spaceCount--;
}
return sb.toString();
}
for (int j = 0; j < count; j++) {
sb.append(" ");
spaceCount--;
}
}
}
return sb.toString();
}
2022.9.8
思路:
k是偶数,后面橙色部分5到2是降序的
k是奇数,后面橙色部分3到5是升序的
蓝色部分,奇数位是升序从1开始,偶数位是降序,从n开始,蓝色部分有k个数
public int[] constructArray(int n, int k) {
int[] res = new int[n];
int i = 0;
// p是奇数位,q是偶数位
int p = 1, q = n;
// 先构造前k个数字,表示不同的k-1个整数
for (int j = 0; j < k; j++) {
// 奇数位从小到大
if (j % 2 == 0) {
res[i] = p;
p++;
// 偶数位从大到小
} else {
res[i] = q;
q--;
}
i++;
}
// 构造剩下的绝对值为1的序列
if (k % 2 == 0) {
// k等于偶数时,后边|ak-1 - ak| = 1的序列一定是降序序列
while (i < n) {
res[i] = q;
q--;
i++;
}
} else {
// k等于奇数时,后边|ak-1 - ak| = 1的序列一定是升序序列
while (i < n) {
res[i] = p;
p++;
i++;
}
}
return res;
}
2022.9.22
思路:
把pieces每个数组的第一个数字作为key,当前数组的索引作为value,遍历arr,看是否有这个key,有的话就遍历key对应的数组比较是否相等,遍历完这个数组下一次arr的起点是i+当前数组的长度
public boolean canFormArray(int[] arr, int[][] pieces) {
int n = arr.length, m = pieces.length;
Map<Integer, Integer> index = new HashMap<Integer, Integer>();
for (int i = 0; i < m; i++) {
index.put(pieces[i][0], i);
}
for (int i = 0; i < n;) {
if (!index.containsKey(arr[i])) {
return false;
}
int j = index.get(arr[i]), len = pieces[j].length;
for (int k = 0; k < len; k++) {
if (arr[i + k] != pieces[j][k]) {
return false;
}
}
i = i + len;
}
return true;
}