坚持最近一个星期把每道题搞熟悉
文章目录
- 1154一年中的第几天
- [125. 验证回文串](https://leetcode.cn/problems/valid-palindrome/)
- [344. 反转字符串](https://leetcode.cn/problems/reverse-string/)
- [20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/)
- [392. 判断子序列](https://leetcode.cn/problems/is-subsequence/)
- [409. 最长回文串](https://leetcode.cn/problems/longest-palindrome/)
- [859. 亲密字符串](https://leetcode.cn/problems/buddy-strings/)
- [14. 最长公共前缀](https://leetcode.cn/problems/longest-common-prefix/)
- [1694. 重新格式化电话号码](https://leetcode.cn/problems/reformat-phone-number/)
- [551. 学生出勤记录 I](https://leetcode.cn/problems/student-attendance-record-i/)
- [1. 两数之和](https://leetcode.cn/problems/two-sum/)
- [169. 多数元素](https://leetcode.cn/problems/majority-element/)
- [53. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/)
- [1502. 判断能否形成等差数列](https://leetcode.cn/problems/can-make-arithmetic-progression-from-sequence/)
- [88. 合并两个有序数组](https://leetcode.cn/problems/merge-sorted-array/)
- [594. 最长和谐子序列](https://leetcode.cn/problems/longest-harmonious-subsequence/)
- [643. 子数组最大平均数 I](https://leetcode.cn/problems/maximum-average-subarray-i/)
- [463. 岛屿的周长](https://leetcode.cn/problems/island-perimeter/)
- [234. 回文链表](https://leetcode.cn/problems/palindrome-linked-list/)
- [21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/)
- [141. 环形链表](https://leetcode.cn/problems/linked-list-cycle/)
- [83. 删除排序链表中的重复元素](https://leetcode.cn/problems/remove-duplicates-from-sorted-list/)
- [468. 验证IP地址](https://leetcode.cn/problems/validate-ip-address/)
- [692. 前K个高频单词](https://leetcode.cn/problems/top-k-frequent-words/)
- [1764. 通过连接另一个数组的子数组得到一个数组](https://leetcode.cn/problems/form-array-by-concatenating-subarrays-of-another-array/)
- [56. 合并区间](https://leetcode.cn/problems/merge-intervals/)
- [229. 多数元素 II](https://leetcode.cn/problems/majority-element-ii/)
- [347. 前 K 个高频元素](https://leetcode.cn/problems/top-k-frequent-elements/)
- [93. 复原 IP 地址](https://leetcode.cn/problems/restore-ip-addresses/)
- [424. 替换后的最长重复字符](https://leetcode.cn/problems/longest-repeating-character-replacement/)
- [15. 三数之和](https://leetcode.cn/problems/3sum/)
- [39. 组合总和](https://leetcode.cn/problems/combination-sum/)
- [90. 子集 II](https://leetcode.cn/problems/subsets-ii/)
- 46.全排列
- [78. 子集](https://leetcode.cn/problems/subsets/)
- [417. 太平洋大西洋水流问题](https://leetcode.cn/problems/pacific-atlantic-water-flow/)
- [994. 腐烂的橘子](https://leetcode.cn/problems/rotting-oranges/)
- 385.迷你语法分析器
- [713. 乘积小于 K 的子数组](https://leetcode.cn/problems/subarray-product-less-than-k/)
- [16. 最接近的三数之和](https://leetcode.cn/problems/3sum-closest/)
- [150. 逆波兰表达式求值](https://leetcode.cn/problems/evaluate-reverse-polish-notation/)
- [70. 爬楼梯](https://leetcode.cn/problems/climbing-stairs/)
- [64. 最小路径和](https://leetcode.cn/problems/minimum-path-sum/)
- [204. 计数质数](https://leetcode.cn/problems/count-primes/)
- [JAVA11 求最小公倍数](https://www.nowcoder.com/practice/feb002886427421cb1ad3690f03c4242?tpId=220&tqId=39062&ru=/exam/oj)
- [HJ28 素数伴侣](https://www.nowcoder.com/practice/b9eae162e02f4f928eac37d7699b352e?tpId=37&tqId=21251&ru=/exam/oj)
- 为何需要重新寻找伴侣
- 实现机制
- 保证最大匹配
- [HJ25 数据分类处理](https://www.nowcoder.com/practice/9a763ed59c7243bd8ab706b2da52b7fd?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E6%95%B0%E6%8D%AE%E5%88%86%E7%B1%BB%E5%A4%84%E7%90%86&sourceUrl=&gioEnter=menu)
- [HJ60 查找组成一个偶数最接近的两个素数](https://www.nowcoder.com/practice/f8538f9ae3f1484fb137789dec6eedb9?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E6%9F%A5%E6%89%BE%E7%BB%84%E6%88%90%E4%B8%80%E4%B8%AA%E5%81%B6%E6%95%B0%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9A%84%E4%B8%A4%E4%B8%AA%E7%B4%A0%E6%95%B0&sourceUrl=&gioEnter=menu)
- [从上到下打印二叉树 III](https://blog.csdn.net/weixin_39035802/article/details/124669764)
- [剑指offer 32 从上到下打印二叉树 II](https://blog.csdn.net/weixin_43412762/article/details/132039623)
- [HJ41 称砝码](https://www.nowcoder.com/practice/f9a4c19050fc477e9e27eb75f3bfd49c?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E7%A7%B0%E7%A0%9D%E7%A0%81&sourceUrl=&gioEnter=menu)
- [76. 最小覆盖子串](https://leetcode.cn/problems/minimum-window-substring/)
- [5. 最长回文子串](https://leetcode.cn/problems/longest-palindromic-substring/)
- [674. 最长连续递增序列](https://leetcode.cn/problems/longest-continuous-increasing-subsequence/)
- [77. 组合](https://leetcode.cn/problems/combinations/)
- 面试题08-有重复字符串的排列组合
- [1614. 括号的最大嵌套深度](https://leetcode.cn/problems/maximum-nesting-depth-of-the-parentheses/)
- [HJ68 成绩排序](https://www.nowcoder.com/practice/8e400fd9905747e4acc2aeed7240978b?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E6%88%90%E7%BB%A9%E6%8E%92%E5%BA%8F&sourceUrl=&gioEnter=menu)
- [OR101 合并区间](https://www.nowcoder.com/practice/0596b6232ce74b18b60ba0367d7f2492?tpId=182&tqId=34827&ru=/exam/oj)
- [HJ27 查找兄弟单词](https://www.nowcoder.com/practice/03ba8aeeef73400ca7a37a5f3370fe68?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E6%9F%A5%E6%89%BE%E5%85%84%E5%BC%9F%E5%8D%95%E8%AF%8D&sourceUrl=&gioEnter=menu)
- [HJ14 字符串排序](https://www.nowcoder.com/practice/5af18ba2eb45443aa91a11e848aa6723?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8E%92%E5%BA%8F&sourceUrl=&gioEnter=menu)
- [HJ8 合并表记录](https://www.nowcoder.com/practice/de044e89123f4a7482bd2b214a685201?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E5%90%88%E5%B9%B6%E8%A1%A8%E8%AE%B0%E5%BD%95&sourceUrl=&gioEnter=menu)
- [HJ106 字符逆序](https://www.nowcoder.com/practice/cc57022cb4194697ac30bcb566aeb47b?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=106&sourceUrl=&gioEnter=menu)
- 输入整型数组和排序标识
- 整数与IP地址间的转换
- 删除字符串中出现次数最少的字符
- [HJ20 密码验证合格程序](https://www.nowcoder.com/practice/184edec193864f0985ad2684fbc86841?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E5%AF%86%E7%A0%81%E9%AA%8C%E8%AF%81%E5%90%88%E6%A0%BC%E7%A8%8B%E5%BA%8F&sourceUrl=&gioEnter=menu)
- [HJ17 坐标移动](https://www.nowcoder.com/practice/119bcca3befb405fbe58abe9c532eb29?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E5%9D%90%E6%A0%87%E7%A7%BB%E5%8A%A8&sourceUrl=&gioEnter=menu)
- 跳台阶
- [HJ10 字符个数统计](https://www.nowcoder.com/practice/eb94f6a5b2ba49c6ac72d40b5ce95f50?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E5%AD%97%E7%AC%A6%E4%B8%AA%E6%95%B0%E7%BB%9F%E8%AE%A1&sourceUrl=&gioEnter=menu)
- [HJ3 明明的随机数](https://www.nowcoder.com/practice/3245215fffb84b7b81285493eae92ff0?tpId=37&ru=%2Fexam%2Foj&difficulty=&judgeStatus=&tags=&title=%E6%98%8E%E6%98%8E%E7%9A%84%E9%9A%8F%E6%9C%BA%E6%95%B0&sourceUrl=&gioEnter=menu)
- 进制转换
1154一年中的第几天
public int dayOfYear(String date) {// format YYYY-MM-DDint year = Integer.parseInt(date.substring(0, 4));int month = Integer.parseInt(date.substring(5, 7));int day = Integer.parseInt(date.substring(8));int[] daysOfMonthList = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 闰月if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {daysOfMonthList[1]++;}int daysBeforeThisMonth = 0;if (month > 1){for (int i = 0; i < month - 1; i++) {daysBeforeThisMonth += daysOfMonthList[i];}}return day+daysBeforeThisMonth;
}
125. 验证回文串
class Solution {public boolean isPalindrome(String s) {int n = s.length();int left = 0;int right = n-1;while(left < right){while(left < right && !Character.isLetterOrDigit(s.charAt(left))){left++;}while(left < right && !Character.isLetterOrDigit(s.charAt(right))){right--;}if(Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))){return false;}left++;right--;}return true;}
}
344. 反转字符串
class Solution {public void reverseString(char[] s) {// 双指针int left = 0;int right = s.length-1;while(left < right){char temp = s[left];s[left] = s[right];s[right] = temp;left++;right--;}}
}
20. 有效的括号
class Solution {public boolean isValid(String s) {// map {} 栈// checkif(s.isEmpty()){return true;}Map<Character,Character> map = new HashMap();map.put(']','[');map.put('}','{');map.put(')','(');Stack<Character> stack = new Stack();for(Character c: s.toCharArray()){if(map.containsKey(c)){// 说明有括号Character topElement = stack.isEmpty()?'#':stack.pop();if(map.get(c) != topElement){return false;}}else{stack.push(c);}}return stack.isEmpty();}
}
392. 判断子序列
class Solution {public boolean isSubsequence(String s, String t) {// 贪心 双指针int n = s.length();int m = t.length();int i =0, j=0;while(i<n && j<m){if(s.charAt(i) == t.charAt(j)){i++;}j++;}return i == n;}
}
409. 最长回文串
class Solution {public int longestPalindrome(String s) {// hash 偶数++ 奇数放中间只能1个Map<Character,Integer> counter = new HashMap();for( int i = 0; i< s.length(); i++){counter.merge(s.charAt(i),1,(a,b)->(a+b));}// 统计构造回文串的最大长度int res = 0, odd = 0 ;for(Map.Entry<Character,Integer> kv: counter.entrySet()){// 当前字符出现次数向下取偶数,并计入resint count = kv.getValue();int rem = count % 2;res += count - rem;// 如果当前字符出现次数是奇数,将odd置位1if(rem == 1){odd = 1;}}return res+odd;}
}
859. 亲密字符串
class Solution {public boolean buddyStrings(String s, String goal) {//check lenif (s.length() != goal.length()){return false;}// equalif (s.equals(goal)){int[] count = new int[26];for (int i = 0; i < s.length(); i++) {int assicCount = s.charAt(i)-'a';count[assicCount]++;//对应字母的频率if (count[assicCount] > 1){// 有重复,只要换重复的就一定相等return true;}}return false;}else {// first secondint first = -1;int second = -1;for (int i = 0; i < s.length(); i++) {// 只能有两个相同位置的字符不一样if (s.charAt(i) != goal.charAt(i)){if (first==-1){first = i;}else if (second==-1){second = i;}else {// 超过两个return false;}}}return (second != -1 && s.charAt(first) == goal.charAt(second) && s.charAt(second) == goal.charAt(first));}}
}
14. 最长公共前缀
class Solution {public String longestCommonPrefix(String[] strs) {// checkif(strs.length ==0){return "";}// 先排序 再比较头尾Arrays.sort(strs);int n = strs.length;String ans = "";for(int i = 0; i< strs[0].length();i++){if(strs[0].charAt(i) == strs[n-1].charAt(i)){ans += strs[0].charAt(i);}else{break;}}return ans;}
}
1694. 重新格式化电话号码
class Solution {public String reformatNumber(String number) {StringBuilder digits = new StringBuilder();for(int i = 0; i < number.length(); i++){char c = number.charAt(i);if(Character.isDigit(c)){digits.append(c);}}int n = digits.length();int currPt = 0;StringBuilder ans = new StringBuilder();while(n > 0){if(n > 4){ans.append(digits.substring(currPt,currPt+3)+"-");n -=3;currPt += 3;}else{if(n==4){ans.append(digits.substring(currPt,currPt+2)+"-"+digits.substring(currPt+2,currPt+4));}else {ans.append(digits.substring(currPt,currPt+n));}break;}}return ans.toString();}
}
551. 学生出勤记录 I
class Solution {public boolean checkRecord(String s) {return s.indexOf('A') == s.lastIndexOf('A') && !s.contains("LLL");}
}
1. 两数之和
class Solution {public int[] twoSum(int[] nums, int target) {// cacheMap<Integer,Integer> cache = new HashMap();for(int i=0;i<nums.length;i++){if(cache.containsKey(target-nums[i])){return new int[]{cache.get(target-nums[i]),i};}cache.put(nums[i],i);}return new int[]{};}
}
169. 多数元素
class Solution {public int majorityElement(int[] nums) {// checkif(nums.length <=2){return nums[nums.length-1];}// 排序后中间元素Arrays.sort(nums);return nums[nums.length/2];}
}
53. 最大子数组和
class Solution {public int maxSubArray(int[] nums) {//checkif(nums == null || nums.length==0){return 0;}int maxCurrent = nums[0]; // 当前元素的子数组和int maxGlobal = nums[0]; // 全局最大子数组和for(int i=1;i<nums.length;i++){// 人生的每个阶段,如果前一个阶段是负积累,及时抛弃,开启新篇章,否则持续积累// 选择当前元素作为新子数组的开始,或者将其添加到前一个元素的子数组中maxCurrent = Math.max(nums[i],maxCurrent+nums[i]);// 每个阶段都要做下总结,是否全局最优// 更新全局最大子数组和maxGlobal = Math.max(maxGlobal,maxCurrent);}return maxGlobal;}
}
1502. 判断能否形成等差数列
class Solution {public boolean canMakeArithmeticProgression(int[] arr) {if(arr.length ==2){return true;}Arrays.sort(arr);int res = arr[1]-arr[0];for(int i=2;i<arr.length;i++){if((arr[i]-arr[i-1]) != res){return false;}}return true;}
}
88. 合并两个有序数组
class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {// 双指针int[] newNums = new int[m+n];int i = 0;int j = 0;int p = 0;while(i<m && j<n){if(nums1[i]<nums2[j]){newNums[p] = nums1[i];p++;i++;}else{newNums[p] = nums2[j];p++;j++;}}if(i<m){// 复制从i到m的元素过去System.arraycopy(nums1,i,newNums,p,m-i);}if(j<n){System.arraycopy(nums2,j,newNums,p,n-j);}// 拷贝到nums1System.arraycopy(newNums,0,nums1,0,m+n);}
}
594. 最长和谐子序列
class Solution {public int findLHS(int[] nums) {Map<Integer,Integer> map = new HashMap();for(int i = 0;i < nums.length;i++){map.put(nums[i],map.getOrDefault(nums[i],0)+1);}int ans = 0;for(int i: map.keySet()){if(map.containsKey(i-1)){ans = Math.max(ans,map.get(i)+map.get(i-1));}}return ans;}
}
643. 子数组最大平均数 I
class Solution {public double findMaxAverage(int[] nums, int k) {int sum = 0;int n = nums.length;for(int i=0;i<k;i++){sum += nums[i];}int maxSum = sum;for(int i=k;i<n;i++){sum = sum - nums[i-k] + nums[i];maxSum = Math.max(maxSum, sum);}return maxSum * 1.0/k;}
}
463. 岛屿的周长
class Solution {public int islandPerimeter(int[][] grid) {int perimeter = 0;int rows = grid.length;int cols = grid[0].length;for(int i=0;i<rows;i++){for(int j = 0; j< cols;j++){// 四个位置,水 或者 越界 再++if(grid[i][j] == 1){// 上方if(i==0 || grid[i-1][j] == 0){perimeter++;}// 下方if(i==rows-1 || grid[i+1][j]==0){perimeter++;}// 左侧if(j==0|| grid[i][j-1]==0){perimeter++;}// 右侧if(j==cols-1 || grid[i][j+1]==0){perimeter++;}}}}return perimeter;}
}
234. 回文链表
class Solution {public boolean isPalindrome(ListNode head) {if(head.next == null){return true;}// stackDeque<ListNode> stack = new ArrayDeque();ListNode newHead = head;while(head!=null){stack.push(head);head = head.next;}while(newHead != null){if(newHead.val != stack.pop().val){return false;}newHead = newHead.next;}return true;}
}
21. 合并两个有序链表
class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode dummy = new ListNode(-1);ListNode head = dummy;while(list1!=null && list2!=null){if(list1.val>list2.val){head.next = list2;head = head.next;list2 = list2.next;}else{head.next = list1;head = head.next;list1 = list1.next;}}while(list1!=null){head.next = list1;head = head.next;list1 = list1.next;}while(list2!=null){head.next = list2;head = head.next;list2 = list2.next;}return dummy.next;}
}
141. 环形链表
public class Solution {public boolean hasCycle(ListNode head) {// checkif(head == null){return false;}// 双指针ListNode fast = head;ListNode slow = head;while(fast.next != null && fast.next.next!= null){fast = fast.next.next;slow = slow.next;if(fast == slow ){return true;}}return false;}
}
83. 删除排序链表中的重复元素
class Solution {public ListNode deleteDuplicates(ListNode head) {if(head == null){return head;}ListNode cur = head;while(cur.next != null){if(cur.val == cur.next.val){cur.next = cur.next.next;}else{cur = cur.next;}}return head;}
}
468. 验证IP地址
class Solution {public String validIPAddress(String queryIP) {if (queryIP.indexOf(".") >= 0) {return isIPv4(queryIP) ? "IPv4" : "Neither";} else {return isIPv6(queryIP) ? "IPv6" : "Neither";}}private boolean isIPv4(String queryIP) {// 加-1防止出现空字符串无法计数 如192.168.1.1,后面多了个点,不加-1会被忽略后面的空串String[] split = queryIP.split("\\.",-1);//个数不是4个if (split.length != 4) {return false;}for (String s : split) {// 每个长度不在1-3之间if (s.length() > 3 || s.length() == 0) {return false;}// 有前导0 并且长度不为1if (s.charAt(0) == '0' && s.length() != 1) {return false;}// 计算数字int ans = 0;for (int j = 0; j < s.length(); j++) {char c = s.charAt(j);if (!Character.isDigit(c)) {return false;}ans = ans * 10 +(c - '0');}//数字超过255if (ans > 255) {return false;}}return true;}public boolean isIPv6(String queryIP) {String[] split = queryIP.split(":", -1);//数量不是8if (split.length != 8) {return false;}for (String s : split) {// 每个串 长度不是1-4之间if (s.length() > 4 || s.length() == 0) {return false;}for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);//不是数字且字母不在a-f之间if (!Character.isDigit(c) && !('a' <= Character.toLowerCase(c) && Character.toLowerCase(c) <= 'f')) {return false;}}}return true;}
}
正则太难了…
692. 前K个高频单词
class Solution {public List<String> topKFrequent(String[] words, int k) {Map<String, Integer> frequencyMap = new HashMap<>();for (String word : words) {frequencyMap.put(word, frequencyMap.getOrDefault(word, 0) + 1);}// 小顶堆PriorityQueue<WordFrequency> minHeap = new PriorityQueue<>();for (Map.Entry<String, Integer> entry : frequencyMap.entrySet()) {minHeap.offer(new WordFrequency(entry.getKey(), entry.getValue()));if (minHeap.size() > k) {minHeap.poll();}}List<String> result = new ArrayList<>();while (!minHeap.isEmpty()) {result.add(minHeap.poll().word);}Collections.reverse(result);return result;}public static class WordFrequency implements Comparable<WordFrequency> {String word;int frequency;public WordFrequency(String word, int frequency) {this.word = word;this.frequency = frequency;}@Overridepublic int compareTo(WordFrequency wordFrequency) {if (this.frequency != wordFrequency.frequency) {return Integer.compare(this.frequency, wordFrequency.frequency);} else {return wordFrequency.word.compareTo(this.word);}}}
}
1764. 通过连接另一个数组的子数组得到一个数组
class Solution {public boolean canChoose(int[][] groups, int[] nums) {//滑动窗口int n = nums.length;int gIndex = 0;int windowStart = 0;while(gIndex < groups.length && windowStart < n){boolean found = false;// 在nums中查找与当前groups[gIndex] 匹配的子序列for(int i=windowStart; i<= n-groups[gIndex].length;i++){boolean match = true;for(int j = 0; j< groups[gIndex].length;j++){if(nums[i+j] != groups[gIndex][j]){match = false;break;}}if(match){found = true;windowStart = i+groups[gIndex].length;break;}}if(!found){return false;}gIndex++;}return gIndex == groups.length;}
}
56. 合并区间
class Solution {public int[][] merge(int[][] intervals) {//checkif(intervals.length <= 1){return intervals;}// 排序Arrays.sort(intervals, (a,b)->a[0] - b[0]);List<int[]> mergedIntervals = new ArrayList();int[] currentInterval = intervals[0];mergedIntervals.add(currentInterval);for(int i=1;i<intervals.length;i++){int[] nextInterval = intervals[i];// current end > next start, 重叠if(currentInterval[1] >= nextInterval[0]){currentInterval[1] = Math.max(currentInterval[1],nextInterval[1]);}else{currentInterval = nextInterval;mergedIntervals.add(currentInterval);}}return mergedIntervals.toArray(new int[mergedIntervals.size()][]);}
}
229. 多数元素 II
class Solution {public List<Integer> majorityElement(int[] nums) {int threshold = nums.length / 3;Map<Integer,Integer> counts = new HashMap();for(int num: nums){counts.put(num, counts.getOrDefault(num,0)+1);}List<Integer> result = new ArrayList();for(Map.Entry<Integer,Integer> entry: counts.entrySet()){if(entry.getValue() > threshold){result.add(entry.getKey());}}return result;}
}
347. 前 K 个高频元素
class Solution {public int[] topKFrequent(int[] nums, int k) {// checkif(nums.length==0 || k == 0){return new int[]{};}// hashMap<Integer,Integer> hash = new HashMap();for(int i=0;i<nums.length;i++){hash.put(nums[i],hash.getOrDefault(nums[i],0)+1);}// PriorityQueuePriorityQueue<Integer> queue = new PriorityQueue<Integer>(k,(v1,v2)->{return hash.get(v1)-hash.get(v2);});// offerfor(int key:hash.keySet()){if(queue.size() < k){queue.offer(key);}else{if(hash.get(key) > hash.get(queue.peek())){queue.poll();queue.offer(key);}}}// resint[] res = new int[k];int i = 0;for(int e: queue){res[i] = e;i++;}return res;}
}
93. 复原 IP 地址
class Solution {public List<String> restoreIpAddresses(String s) {List<String> result = new ArrayList();backtrace(s,0,new ArrayList(),result);return result;}private void backtrace(String s,int start,List<String> currentPath,List<String> result){//如果已经分割了4部分,并且到达了字符串的末尾if(start == s.length() && currentPath.size() == 4){result.add(String.join(".", currentPath));return;}if(currentPath.size() > 4){return;}//从当前起始位置开始,尝试分割长度为1到3的片段for(int end = start;end < Math.min(start+3,s.length()); end++){String segment = s.substring(start, end+1);if((segment.length() > 1 && segment.startsWith("0")) || Integer.parseInt(segment) > 255){continue;}currentPath.add(segment);backtrace(s,end+1,currentPath,result);// 回溯:移除刚加入的片段,尝试其他分割方式currentPath.remove(currentPath.size() -1);}}
}
424. 替换后的最长重复字符
class Solution {public int characterReplacement(String s, int k) {int left = 0, right = 0;int maxLength = 0;Map<Character,Integer> charFrequency = new HashMap();while(right < s.length()){charFrequency.put(s.charAt(right), charFrequency.getOrDefault(s.charAt(right),0)+1);// 当前窗口需要替换的最大次数int maxFreqCharCount = getMaxFrequency(charFrequency);// 当前窗口大小 - 窗口内出现次数最多的字符数量<k,说明还有替换机会while(right-left+1 -maxFreqCharCount > k){//缩小窗口charFrequency.put(s.charAt(left), charFrequency.get(s.charAt(left))-1);left++;}//更新最长子串长度maxLength = Math.max(maxLength,right-left+1);right++;}return maxLength;}private int getMaxFrequency(Map<Character,Integer> frequencyMap){int maxFreq = 0;for(int freq: frequencyMap.values()){maxFreq = Math.max(maxFreq,freq);}return maxFreq;}
}
15. 三数之和
class Solution {public List<List<Integer>> threeSum(int[] nums) {// checkif(nums == null || nums.length < 3){return null;}List<List<Integer>> result = new ArrayList<>();// 排序Arrays.sort(nums);// 双指针夹逼for(int i = 0; i< nums.length-2;i++){int j = i+1;int k = nums.length-1;if(nums[i]>0){break;}if(i>0 && nums[i]==nums[i-1]){continue;}while(j < k){int a = nums[i];int b = nums[j];int c = nums[k];if(a+b+c < 0){j++;}else if(a+b+c > 0){k--;}else{List<Integer> list = new ArrayList<>();list.add(a);list.add(b);list.add(c);result.add(list);while(j<k && nums[j+1] == nums[j]){j++;}while(j<k && nums[k-1] == nums[k]){k--;}j++;k--;}}}return result;}
}
39. 组合总和
class Solution {public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> result = new ArrayList();if(candidates == null || candidates.length == 0){return result;}List<Integer> currentCombination = new ArrayList();backtrace(candidates,target,0,currentCombination, result);return result;}private void backtrace(int[] candidates,int target,int start,List<Integer> currentCombination, List<List<Integer>> result){if(target < 0){// 小于0,此路不通,直接返回return;}if(target == 0){//刚好为0,找到合法组合,加入结果集result.add(new ArrayList<>(currentCombination));return;}//start 开始遍历,允许重复使用同一个元素for(int i = start; i < candidates.length;i++){//选择当前元素currentCombination.add(candidates[i]);backtrace(candidates,target-candidates[i],i,currentCombination,result);//撤销选择,尝试下一个元素currentCombination.remove(currentCombination.size()-1);}}
}
90. 子集 II
class Solution {public List<List<Integer>> subsetsWithDup(int[] nums) {List<List<Integer>> result = new ArrayList();Arrays.sort(nums);List<Integer> temp = new ArrayList();backtrace(result,temp,nums,0);return result;}private void backtrace(List<List<Integer>> result,List<Integer> temp,int[] nums, int start){result.add(new ArrayList<>(temp)); // 添加当前组合到结果集for(int i = start; i < nums.length; i++){// 如果当前元素和前一个相同,并且前一个已经被用了(在同一个层级的循环中)// 跳过当前元素,避免生成重复的子集if(i> start && nums[i] == nums[i-1]){continue;}temp.add(nums[i]);backtrace(result,temp,nums,i+1); //递归生成当前选择为基础的子集temp.remove(temp.size()-1);// 撤销选择,回溯到上一层}}
}
46.全排列
class Solution {public List<List<Integer>> permute(int[] nums) {List<List<Integer>> result = new ArrayList();List<Integer> currentPermutation = new ArrayList();boolean[] used = new boolean[nums.length];// 递归进行全排列generatePermutation(nums,result,currentPermutation,used);return result;}private void generatePermutation(int[] nums,List<List<Integer>> result,List<Integer> currentPermutation,boolean[] used){if(currentPermutation.size() == nums.length){//排列已满,添加到结果集result.add(new ArrayList<>(currentPermutation));return;}for(int i=0;i<nums.length;i++){if(!used[i]){used[i] = true;currentPermutation.add(nums[i]);//递归生成剩余元素的全排列generatePermutation(nums,result,currentPermutation,used);//回溯,撤销选择used[i] = false;currentPermutation.remove(currentPermutation.size()-1);}}}
}
78. 子集
class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> result = new ArrayList();// 添加空集为起始result.add(new ArrayList());List<Integer> currentSubset = new ArrayList();generateSubsets(nums,0,currentSubset,result);return result;}private void generateSubsets(int[] nums, int index, List<Integer> currentSubset,List<List<Integer>> result){if(index == nums.length){return;}// 选择当前元素currentSubset.add(nums[index]);result.add(new ArrayList<>(currentSubset));generateSubsets(nums,index+1,currentSubset,result);//不选择当前元素,从子集移除当前元素currentSubset.remove(currentSubset.size()-1);//递归生成不包含当前元素的子集generateSubsets(nums,index+1,currentSubset,result);}
}
417. 太平洋大西洋水流问题
定义了四个方向,然后分别对矩阵的上下左右边界执行深度优先搜索,标记出能够流向太平洋和大西洋的单元格。之后遍历整个矩阵,找出同时标记为可达太平洋和大西洋的单元格,将其坐标添加到结果列表中
class Solution {// right left up downprivate int[][] directions = {{0,1},{0,-1},{1,0},{-1,0}};private int m,n;public List<List<Integer>> pacificAtlantic(int[][] heights) {m = heights.length;n = heights[0].length;boolean[][] pacificReachable = new boolean[m][n];boolean[][] atlanticReachable = new boolean[m][n];//分别从边界出发,进行DFS,标记能到达太平洋和大西洋的点for(int i=0; i<m; i++){dfs(heights,pacificReachable,i,0);//updfs(heights,atlanticReachable,i,n-1);//down}for(int j = 0; j<n;j++){dfs(heights,pacificReachable,0,j);//leftdfs(heights,atlanticReachable,m-1,j);//right}// 找出同时能到达太平洋和大西洋的点List<List<Integer>> result = new ArrayList();for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(pacificReachable[i][j] && atlanticReachable[i][j]){result.add(Arrays.asList(i,j));}}}return result;}private void dfs(int[][] heights,boolean[][] reachable, int r,int c){reachable[r][c] = true;for(int[] dir: directions){int newRow = r+dir[0];int newCol = c+dir[1];if(newRow >=0 && newRow < m && newCol >= 0 && newCol < n && !reachable[newRow][newCol] && heights[newRow][newCol]>=heights[r][c]){dfs(heights,reachable,newRow,newCol);}}}
}
994. 腐烂的橘子
先遍历整个二维数组,统计新鲜橘子的数量并收集所有腐烂橘子的初始位置。然后,它使用BFS逐步腐烂新鲜橘子,同时跟踪经过的总分钟数。如果所有橘子都能腐烂,则返回分钟数;否则,若仍有新鲜橘子剩余,则返回-1
class Solution {public int orangesRotting(int[][] grid) {int m = grid.length;//行数int n = grid[0].length;//列数int freshOranges = 0;Queue<int[]> rottenQueue = new LinkedList<>(); //腐烂橘子的队列// 初始化for(int i=0; i<m;i++){for(int j = 0; j<n;j++){if(grid[i][j] == 1){freshOranges++;}else if(grid[i][j]==2){rottenQueue.offer(new int[]{i,j});}}}int minutes = 0; int[][] directions = {{-1,0},{1,0},{0,-1},{0,1}};while(!rottenQueue.isEmpty() && freshOranges > 0){// 当前轮次待处理的腐烂橘子数int queueSize = rottenQueue.size();for(int i=0; i< queueSize;i++){int[] rotten = rottenQueue.poll();for(int[] direction: directions){int newX = rotten[0] + direction[0];int newY = rotten[1] + direction[1];// 检查新位置是否在网格内且是新鲜橘子if(newX >= 0 && newX < m && newY >= 0 && newY < n && grid[newX][newY] == 1){grid[newX][newY] = 2;freshOranges--;rottenQueue.offer(new int[]{newX,newY});}}}//如果这一轮有橘子腐烂,增加一分钟if(!rottenQueue.isEmpty()){minutes++;}}//如果还有没腐烂的,返回-1return freshOranges == 0?minutes:-1;}
}
385.迷你语法分析器
先检查输入字符串的第一个字符,以确定是直接解析整数还是进入解析嵌套列表的逻辑。对于嵌套列表的解析,它使用一个栈来维护当前解析的嵌套层次。遍历字符串时,遇到 [
时入栈一个新的 NestedInteger
实例,遇到 ]
时出栈,表示当前子列表完成。对于数字,连续读取直到遇到非数字字符,然后将其转换为 NestedInteger
并添加到当前栈顶的列表中。最后返回最外层的 NestedInteger
对象,即整个字符串解析的结果。
/*** // This is the interface that allows for creating nested lists.* // You should not implement it, or speculate about its implementation* public interface NestedInteger {* // Constructor initializes an empty nested list.* public NestedInteger();** // Constructor initializes a single integer.* public NestedInteger(int value);** // @return true if this NestedInteger holds a single integer, rather than a nested list.* public boolean isInteger();** // @return the single integer that this NestedInteger holds, if it holds a single integer* // Return null if this NestedInteger holds a nested list* public Integer getInteger();** // Set this NestedInteger to hold a single integer.* public void setInteger(int value);** // Set this NestedInteger to hold a nested list and adds a nested integer to it.* public void add(NestedInteger ni);** // @return the nested list that this NestedInteger holds, if it holds a nested list* // Return empty list if this NestedInteger holds a single integer* public List<NestedInteger> getList();* }*/
class Solution {public NestedInteger deserialize(String s) {if(s.charAt(0)!='[') {return new NestedInteger(Integer.valueOf(s));}Queue<Character> q=new LinkedList<>();for(char c:s.toCharArray()){q.offer(c);}// 弹出第一个'['q.poll();return dfs(q);}public NestedInteger dfs(Queue<Character> q){NestedInteger res=new NestedInteger();int sign=1;int num=0;while(!q.isEmpty()){char c=q.poll();if(c==','){continue;}else if(c=='['){res.add(dfs(q));}else if(c=='-'){sign=-1;}else if(c==']'){return res;}else {num=10*num+sign*(c-'0');if(q.peek()==','||q.peek()==']'){ res.add(new NestedInteger(num));num = 0;sign = 1;}}}return res;}
}
713. 乘积小于 K 的子数组
class Solution {public int numSubarrayProductLessThanK(int[] nums, int k) {if(k <=1){return 0;}int left = 0,product = 1, count = 0;for(int right = 0;right < nums.length;right++){product *= nums[right];while(product >= k){product /= nums[left++];}count+= right-left+1;//当前窗口的子数组个数}return count;}
}
16. 最接近的三数之和
class Solution {public int threeSumClosest(int[] nums, int target) {Arrays.sort(nums);// 初始化int closestSum = nums[0]+nums[1]+nums[2];int minDiff = Math.abs(closestSum-target);for(int i = 0; i<nums.length -2; i++){// 跳过重复元素,避免重复计算if(i > 0 && nums[i] == nums[i-1]){continue;}int left = i+1, right = nums.length-1;while(left < right){int sum = nums[i]+nums[left]+nums[right];int diff = Math.abs(sum-target);//更新最接近的和、差值if(diff < minDiff){minDiff = diff;closestSum = sum;}//移动指针if(sum < target){left++;}else if(sum > target){right--;}else{//正好相等return sum;}}}return closestSum;}
}
150. 逆波兰表达式求值
class Solution {public int evalRPN(String[] tokens) {Deque<Integer> stack = new ArrayDeque();for(String token: tokens){switch(token){case "+":stack.push(stack.pop() + stack.pop());break;case "-":int right = stack.pop();int left = stack.pop();stack.push(left-right);break;case "*":stack.push(stack.pop() * stack.pop());break;case "/":right = stack.pop();left = stack.pop();stack.push(left/right);//整除,自动向零截断break;default:stack.push(Integer.parseInt(token));break;}}return stack.pop(); //最后剩下的就是表达式的结果}
}
70. 爬楼梯
class Solution {public int climbStairs(int n) {if(n<=2){return n;}//初始化int[] dp = new int[n+1];dp[1] = 1;dp[2] = 2;for(int i=3;i<=n;i++){// 当前阶的方法数 = 前一阶的 + 前两阶的dp[i] = dp[i-1]+dp[i-2];}return dp[n];}
}
64. 最小路径和
class Solution {public int minPathSum(int[][] grid) {int m = grid.length; //网格的行数int n = grid[0].length;//网格的列数//初始化int[][] dp = new int[m][n];//初始化第一行和第一列dp[0][0] = grid[0][0];for(int i=1;i<m;i++){dp[i][0] = dp[i-1][0]+grid[i][0];//第一列的值依赖上方的值}for(int j = 1;j<n;j++){dp[0][j] = dp[0][j-1]+grid[0][j];//第一行的值依赖左侧的值}//填充其余部分for(int i=1;i<m;i++){for(int j=1;j<n;j++){// 到达(i,j) 的最小路径和 = 上方和左侧的最下路径和 + 当前位置的值dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];}}// 右下角即为所求的最小路径和return dp[m-1][n-1];}
}
204. 计数质数
首先初始化一个布尔数组isPrime
,用于标记从2到n-1的每个数是否为质数。初始时,假设所有数都是质数。然后,从2开始,对于每个标记为质数的数i,将其所有的倍数标记为非质数(因为它们肯定不是质数)。这个过程一直进行到sqrt(n),因为大于sqrt(n)的非质数在其平方根之前已经被标记过了。最后,遍历数组,统计标记为true的元素个数,即为小于n的质数数量
class Solution {public int countPrimes(int n) {if(n<=2){return 0;}int count = 0;boolean[] isPrime = new boolean[n];Arrays.fill(isPrime,true);isPrime[0] = isPrime[1] = false;for(int i=2;i*i<n;i++){if(isPrime[i]){for(int j=i*i;j<n;j+=i){isPrime[j] = false;}}}//直接累加计数,而不是再次遍历for(int i=2;i<n;i++){if(isPrime[i]){count++;}}return count;}
}
JAVA11 求最小公倍数
牛客网
import java.util.*;public class Main {public static void main(String[] args) {Scanner console = new Scanner(System.in);int m = console.nextInt();int n = console.nextInt();int result = getCM(m, n);System.out.println(result);}public static int getCM(int m, int n){if(m == 0 || n == 0){return 0; //任何数和0 的最小公倍数是0}return Math.abs(m*n) / gcd(m,n);}// 计算最大公约数(GCD)的欧几里得算法private static int gcd(int a,int b){while(b != 0){int temp = b;b = a % b;a = temp;}return a;}
}
HJ28 素数伴侣
为何需要重新寻找伴侣
当为某个奇数找到了一个偶数伴侣,并且这个偶数原先已经有伴侣时,我们实际上打破了原有的一个匹配对。为了保持匹配的最大化,我们需要确保被替换掉的奇数(原偶数的伴侣)也能找到一个新的匹配,这样才能保证整体匹配数的增加而不是简单的交换。
实现机制
在find
函数中,当为奇数odd
找到一个与之匹配的偶数,并且这个偶数之前已经有了伴侣(evensMatch[i] != 0
),代码会递归调用find(evensMatch[i], evens, used, evensMatch)
。这一步是为了尝试为那个被替换的奇数(evensMatch[i]
)重新找到一个伴侣。如果成功,意味着原伴侣(evensMatch[i]
)找到了新的匹配,释放了当前偶数与新奇数(odd
)的匹配,整体的匹配对数得以增加。
保证最大匹配
通过这种方式,算法不断探索所有可能的匹配组合,确保了在每次为一个奇数找到匹配时,都能尽量维持或增加整体的匹配对数,避免了局部最优解,从而向全局最优解靠近。简言之,递归重找伴侣是为了在有限的资源(偶数)中,通过调整和优化,达到最多“素数伴侣”对的目的。
public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();//输入的数字先分为 奇数、偶数 两组List<Integer> evenList = new ArrayList<>();List<Integer> oddList = new ArrayList<>();for (int i = 0; i < n; i++) {int j = sc.nextInt();if (isEven(j)) {evenList.add(j);} else {oddList.add(j);}}int size = evenList.size();int count = 0;//已经匹配的数的伴侣int[] evensMatch = new int[size];for (Integer odd : oddList) {//标记对应的数是否查找过int[] used = new int[size];if (find(odd, evenList, used, evensMatch)) {count++;}}System.out.println(count);sc.close();}private static boolean isPrime(int n) {// 除1和自身,不能被其他自然数整除if (n <= 1) {return false;} else {for (int i = 2; i < n; i++) {if (n % i == 0) {return false;}}}return true;}private static boolean isEven(int n) {return (n %2 )==0;}private static boolean find(int odd, List<Integer> evens, int[] used, int[] evensMatch) {//便利偶数:检查当前传入的奇数是否与那些偶数匹配for (int i = 0; i < evens.size(); i++) {if (isPrime(odd + evens.get(i)) && used[i] == 0) {// 设置当前偶数匹配为trueused[i] =1;//如果第 i 个偶数没有伴侣//或者第 i 个偶数原来有伴侣,并且该伴侣能重新找到伴侣// 奇数odd可被设置为第 i 个偶数的伴侣//采用匈牙利算法,能让就让if (evensMatch[i] == 0 || find(evensMatch[i], evens, used, evensMatch)) {evensMatch[i] = odd;return true;}}}//遍历完偶数都没有可以做伴侣的,奇数没有配对return false;}
HJ25 数据分类处理
-
读取输入数据:程序首先使用
Scanner
类从标准输入读取数据。首先读取一个整数I
,表示序列I的长度;接着读取I
个整数,填充到数组arrI
中,这是整数序列I。随后读取一个整数r
,表示序列R的长度;最后读取r
个整数,这些整数将构成序列R,但首先会放入一个TreeSet
(红黑树实现的集合)中以自动排序并去重。 -
数据处理:
- 使用
TreeSet<Integer> treeSet
来存储序列R中的整数,确保它们是去重且排序的。 - 对于
treeSet
中的每个整数integer
,执行以下操作:- 初始化一个计数器
count
用于记录有多少个整数I满足条件(即包含当前R中的整数)。 - 创建一个临时列表
temp
,用于存储满足条件的I的索引和值。 - 遍历数组
arrI
,将每个整数转换成字符串形式,并检查是否包含当前的integer
(通过String.contains()
方法)。- 如果包含,增加
count
计数,并将索引和该整数值加入到temp
列表中。
- 如果包含,增加
- 当前
integer
对应的处理结束后,如果count
大于0,说明有满足条件的I,此时将integer
、满足条件的个数count
以及temp
列表的内容添加到最终结果列表list
中。
- 初始化一个计数器
- 使用
-
整理输出:
- 在输出之前,先在
list
的最前方添加一个元素,表示后续整数序列的个数(不包括这个计数本身)。 - 最后,遍历
list
,将所有元素打印出来,每个元素后面跟一个空格。
- 在输出之前,先在
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { // I 的个数 int countI = sc.nextInt(); int[] arraysI = new int[countI];//序列I for (int i = 0; i < countI; i++) { arraysI[i] = sc.nextInt(); } int countR = sc.nextInt(); TreeSet<Integer> treeSetR = new TreeSet<>();//序列R,对R序列进行排序去重 for (int i = 0; i < countR; i++) { treeSetR.add(sc.nextInt()); } ArrayList<Integer> result = getResult(treeSetR, arraysI); //输出结果 for (Integer integer : result) { System.out.print(integer + " "); } }
} private static ArrayList<Integer> getResult(TreeSet<Integer> treeSetR, int[] arraysI) { ArrayList<Integer> result = new ArrayList<>();//保存最终结果 for (Integer integer : treeSetR) { //查找是否有满足条件的I int count = 0;//统计满足个数 ArrayList<Integer> temp = new ArrayList<>();//临时列表,保存索引,以及对应值 for (int i = 0; i < arraysI.length; i++) { String str = String.valueOf(arraysI[i]);//I整数对应的数字需要连续包含R<i>对应的数字 if (str.contains(String.valueOf(integer))) { //只要有一个满足条件就保存R<i>,保存个数,索引,具体I count++; temp.add(i); temp.add(arraysI[i]); } } if (count > 0) { //按顺序保存对应数据 result.add(integer); result.add(count); result.addAll(temp); } } //统计序列总个数 result.add(0, result.size()); return result;
}
}
HJ60 查找组成一个偶数最接近的两个素数
import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while(scanner.hasNextInt()){int targetNum = scanner.nextInt();if(targetNum <=2 || targetNum %2 != 0){System.out.println("输入应该为大于2的偶数");continue;}int lowerBound = targetNum/2;int upperBound = targetNum/2;while(lowerBound > 2 && upperBound< targetNum-2){if(isPrime(lowerBound) && isPrime(upperBound) && lowerBound+upperBound == targetNum){break;}else{lowerBound--;upperBound++;}}System.out.println(lowerBound);System.out.println(upperBound);}scanner.close();}private static boolean isPrime(int number){if(number <=2){return false;}//平方根 因为一个数的所有可能除数都不会超过其平方根for(int i=2;i<Math.sqrt(number);i++){if(number % i ==0){return false;} }return true;}
}
从上到下打印二叉树 III
leetcode没有版权了,找不到,暂时先在csdn看吧
接受一个二叉树的根节点作为输入,然后返回一个二维列表,其中每个子列表代表二叉树每一层的节点值,且根据之字形顺序排列。这里使用了两个栈来实现层次遍历,并通过leftToRight
布尔变量来控制当前层遍历时的方向(从左到右或从右到左)。在遍历过程中,根据当前层的遍历方向决定如何将孩子节点压入栈中,以实现之字形遍历的效果
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {List<List<Integer>> result = new ArrayList<>();if (root == null) {return result;}Stack<TreeNode> currentLevel = new Stack<>();Stack<TreeNode> nextLevel = new Stack<>();currentLevel.push(root);boolean leftToRight = true; // 标记当前层的遍历方向while (!currentLevel.isEmpty()) {List<Integer> levelValues = new ArrayList<>();while (!currentLevel.isEmpty()) {TreeNode node = currentLevel.pop();levelValues.add(node.val);// 根据当前层的遍历方向来决定孩子节点的入栈顺序if (leftToRight) {if (node.left != null) {nextLevel.push(node.left);}if (node.right != null) {nextLevel.push(node.right);}} else {if (node.right != null) {nextLevel.push(node.right);}if (node.left != null) {nextLevel.push(node.left);}}}result.add(levelValues);// 交换两个栈,准备下一层的遍历Stack<TreeNode> temp = currentLevel;currentLevel = nextLevel;nextLevel = temp;// 改变遍历方向leftToRight = !leftToRight;}return result;}
剑指offer 32 从上到下打印二叉树 II
使用了一个队列来保存每一层的节点,初始时将根节点入队。进入循环后,首先获取当前层的节点数量,然后遍历这一层的每个节点,打印节点值,并将其左右孩子节点(如果存在)入队。每完成一层的遍历后,通过换行来区分不同层的输出
public class SolutionJZ32two {public static void main(String[] args) {// 示例创建二叉树,实际使用时可以通过读取输入动态生成TreeNode root = new TreeNode(1);root.left = new TreeNode(2);root.right = new TreeNode(3);root.left.left = new TreeNode(4);root.left.right = new TreeNode(5);printTreeByLevel(root);}public static void printTreeByLevel(TreeNode root) {if (root == null) {return;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while (!queue.isEmpty()) {int levelSize = queue.size();for (int i = 0; i < levelSize; i++) {TreeNode currentNode = queue.poll();System.out.print(currentNode.val + " ");if (currentNode.left != null) {queue.offer(currentNode.left);}if (currentNode.right != null) {queue.offer(currentNode.right);}}System.out.println(); // 换行,表示这一层打印完毕}}
}
HJ41 称砝码
- 使用两层循环遍历每一种砝码及其数量。外层循环遍历砝码种类,内层循环则基于当前砝码的数量生成所有可能的累加重量。
- 对于每种砝码,通过一个临时的
HashSet
newWeights
来收集新生成的所有可能总重量,这一步是为了避免直接修改正在迭代的集合而引发的并发修改异常。 - 内部还有一个循环遍历
allWeights
中已有的所有重量,并将当前砝码的每个可能累加重量(从1倍到其数量倍)都加到这些已知重量上,然后将结果加入到newWeights
中。 - 每处理完一种砝码后,将
newWeights
的内容替换到allWeights
中,准备处理下一种砝码
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNextInt()) {int n = in.nextInt();int[] weights = new int[n];int[] counts = new int[n];for (int i = 0; i < n; i++) {weights[i] = in.nextInt();}for (int i = 0; i < n; i++) {counts[i] = in.nextInt();}Set<Integer> allWeights = new HashSet<>();allWeights.add(0); // 包含重量0// 直接通过循环构建所有可能的重量组合for (int i = 0; i < n; i++) {Set<Integer> newWeights = new HashSet<>(allWeights); // 避免修改原集合导致并发修改异常for (int count = 1; count <= counts[i]; count++) {for (int existingWeight : allWeights) {newWeights.add(existingWeight + weights[i] * count);}}allWeights = newWeights;}System.out.println(allWeights.size());}in.close();}
}
76. 最小覆盖子串
class Solution {public String minWindow(String s, String t) {// checkif(s==null || t==null || s.isEmpty() || t.isEmpty() || s.length() < t.length()){return "";}//双mapMap<Character, Integer> map = new HashMap();for(char c: t.toCharArray()){map.put(c,map.getOrDefault(c,0)+1);}Map<Character, Integer> window = new HashMap();//初始化int left,right,count,minLeft,minLen;left = right = count = minLeft = 0;minLen = Integer.MAX_VALUE;while(right < s.length()){//putchar c = s.charAt(right);if(map.containsKey(c)){window.put(c,window.getOrDefault(c,0)+1);//更新countif(window.get(c).intValue() == map.get(c).intValue()){count++;}}// 满了while(count == map.size()){//计数int currentLen = right - left +1;if(currentLen < minLen){minLen = currentLen;minLeft = left;}//收缩char leftChar = s.charAt(left);if(map.containsKey(leftChar)){// --window.put(leftChar, window.get(leftChar)-1);if(window.get(leftChar) < map.get(leftChar)){count--;}}left++;}right++;}return minLen==Integer.MAX_VALUE?"":s.substring(minLeft,minLeft+minLen);}
}
5. 最长回文子串
class Solution {public String longestPalindrome(String s) {if (s == null || s.length() < 1) return "";int start = 0, end = 0;for (int i = 0; i < s.length(); i++) {// 奇数长度的回文int len1 = expandAroundCenter(s, i, i);// 偶数长度的回文int len2 = expandAroundCenter(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);}private int expandAroundCenter(String s, int left, int right) {while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {left--;right++;}return right - left - 1; // 返回回文子串的长度}
}
674. 最长连续递增序列
class Solution {public int findLengthOfLCIS(int[] nums) {if (nums == null || nums.length == 0) {return 0;}int maxLength = 1; // 最长连续递增子序列的长度,默认至少为1(数组至少有一个元素)int currentLength = 1; // 当前连续递增子序列的长度for (int i = 1; i < nums.length; i++) {// 如果当前元素大于前一个元素,说明连续递增,当前长度加1if (nums[i] > nums[i - 1]) {currentLength++;// 更新最长连续递增子序列长度maxLength = Math.max(maxLength, currentLength);} else {// 遇到非递增元素,重置当前连续递增序列长度currentLength = 1;}}return maxLength;}
}
77. 组合
class Solution {public List<List<Integer>> combine(int n, int k) {List<List<Integer>> results = new ArrayList<>();List<Integer> combination = new ArrayList<>();backtrack(results, combination, 1, n, k);return results;}private static void backtrack(List<List<Integer>> results, List<Integer> combination, int start, int n, int k) {if (combination.size() == k) {results.add(new ArrayList<>(combination));return;}for (int i = start; i <= n; i++) {// 添加当前数字到组合中combination.add(i);// 递归生成下一个数字,从i+1开始,确保组合内的数字严格递增backtrack(results, combination, i + 1, n, k);// 回溯,移除最后一个添加的数字,尝试下一个可能的数字combination.remove(combination.size() - 1);}}
}
面试题08-有重复字符串的排列组合
class Solution {public String[] permutation(String S) {char[] chars = S.toCharArray();List<String> result = new ArrayList<>();boolean[] used = new boolean[chars.length];Arrays.sort(chars); // 先排序,使得相同字符相邻backtrack(chars, used, new StringBuilder(), result);return result.toArray(new String[0]);}private static void backtrack(char[] chars, boolean[] used, StringBuilder current, List<String> result) {if (current.length() == chars.length) {result.add(current.toString());return;}for (int i = 0; i < chars.length; i++) {// 如果当前字符已经使用过并且它的前一个字符和它相同,并且前一个字符还没有被使用过,// 那么跳过当前字符,避免生成重复的排列if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) {continue;}if (!used[i]) {used[i] = true;current.append(chars[i]);backtrack(chars, used, current, result);current.deleteCharAt(current.length() - 1); // 回溯used[i] = false;}}}
}
1614. 括号的最大嵌套深度
class Solution {public int maxDepth(String s) {int depth = 0; // 当前的嵌套深度int maxDepth = 0; // 记录最大嵌套深度for (char ch : s.toCharArray()) {if (ch == '(') {depth++; // 遇到左括号,深度增加maxDepth = Math.max(maxDepth, depth); // 更新最大深度} else if (ch == ')') {depth--; // 遇到右括号,深度减少// 确保深度不会变成负数,虽然有效的括号字符串应该不会发生这种情况,但作为防御性编程depth = Math.max(depth, 0);}}return maxDepth;}
}
HJ68 成绩排序
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(); // 读取人数int order = scanner.nextInt(); // 读取排序方式,0-从高到低,1-从低到高ArrayList<Student> students = new ArrayList<>();for (int i = 0; i < n; i++) {String name = scanner.next();int score = scanner.nextInt();students.add(new Student(name, score));}// 根据排序要求调整比较逻辑if (order == 0) { // 如果是0,则需要从高到低排序,Collections.reverseOrder()可以实现Collections.sort(students, Collections.reverseOrder());} else {Collections.sort(students);}for (Student student : students) {System.out.println(student);}}public static class Student implements Comparable<Student> {String name;int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic int compareTo(Student other) {// 按成绩排序,成绩相同则按照录入顺序(ArrayList的自然顺序)if (this.score != other.score) {return Integer.compare(this.score,other.score); } else {return this.name.compareTo(other.name); // 同分情况下,按照姓名字典序}}@Overridepublic String toString() {return name + " " + score;}}}
OR101 合并区间
使用mergeScopes
方法对区间进行合并处理,最后输出合并结果。区间类Scope
用于存储区间的起始和结束位置
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);List<Scope> scopeList = newArrayList<>(); // 创建一个列表来存储输入的区间范围// 读取输入的区间数据,直到没有更多输入为止while (scanner.hasNext()) {String line = scanner.next();String[] parts =line.split(","); // 将输入的字符串以逗号分割成开始和结束的两个部分int start = Integer.parseInt(parts[0]); // 解析开始的整数部分int end = Integer.parseInt(parts[1]); // 解析结束的整数部分scopeList.add(new Scope(start, end)); // 将区间添加到列表中}// 调用方法来合并所有重叠的区间List<Scope> mergedScopes = mergeScopes(scopeList);// 构建输出字符串,展示合并后的区间StringBuilder output = new StringBuilder();for (Scope scope : mergedScopes) {output.append(scope.start).append(",").append(scope.end).append(" ");}System.out.println(output.toString().trim()); // 输出最终的合并区间,去除尾部空格}// 方法用于合并有重叠的区间public static List<Scope> mergeScopes(List<Scope> scopes) {if (scopes.isEmpty()) returnCollections.emptyList(); // 如果输入区间为空,直接返回空列表// 先按照区间的起始位置进行排序Collections.sort(scopes, Comparator.comparingInt(scope -> scope.start));List<Scope> result = newArrayList<>(); // 创建一个新的列表来存储合并后的区间Scope currentScope = scopes.get(0); // 初始化当前区间为排序后的第一个区间for (int i = 1; i < scopes.size(); i++) { // 从第二个区间开始遍历Scope nextScope = scopes.get(i); // 获取下一个区间if (currentScope.end >=nextScope.start) { // 如果当前区间结束位置大于等于下一区间的开始位置,说明有重叠// 合并区间:更新当前区间的结束位置为两者中较大的那个currentScope.end = Math.max(currentScope.end, nextScope.end);} else {// 无重叠,将当前区间加入结果列表,并将下一个区间设为当前区间继续比较result.add(currentScope);currentScope = nextScope;}}// 确保最后一个区间也被加入到结果中result.add(currentScope);return result; // 返回合并后的区间列表}// 定义区间类static class Scope {int start, end; // 区间的开始和结束位置Scope(int start, int end) {this.start = start;this.end = end;}}
}
HJ27 查找兄弟单词
通过遍历字典找出所有目标单词的兄弟单词,然后对这些兄弟单词进行排序,并输出满足条件的第k个兄弟单词。如果没有足够的兄弟单词满足 k
的要求,则不输出具体单词
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNext()) {String[] ss = scanner.nextLine().split(" ");Integer a = Integer.parseInt(ss[0]);String x = ss[ss.length - 2];Integer k = Integer.parseInt(ss[ss.length - 1]);List<String> list = new ArrayList<>();for (int i = 1; i <= a ; i++) {if (isBrother(x, ss[i])) {list.add(ss[i]);}}int size = list.size();System.out.println(size);if (size >= k) {Collections.sort(list);System.out.println(list.get(k - 1));}}}public static boolean isBrother(String x, String y) {if (x.length() != y.length() || y.equals(x)) {return false;}char[] s = x.toCharArray();char[] j = y.toCharArray();Arrays.sort(s);Arrays.sort(j);return new String(s).equals(new String(j));}
}
HJ14 字符串排序
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();String[] array = new String[n];for (int i = 0; i < n; i++) {array[i] = in.next();}Arrays.sort(array);for (String str : array) {System.out.println(str);}}
}
HJ8 合并表记录
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int tableSize = scanner.nextInt();Map<Integer,Integer> table = new TreeMap<>();for(int i=0;i<tableSize;i++){int key = scanner.nextInt();int value = scanner.nextInt();if(table.containsKey(key)){table.put(key,table.get(key)+value);}else{table.put(key,value);}}for(Integer key: table.keySet()){System.out.println(key+" "+table.get(key));}}
}
HJ106 字符逆序
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);while(in.hasNextLine()){String str = in.nextLine();System.out.println(reverse(str));}}private static String reverse(String str){StringBuilder res = new StringBuilder(str);return res.reverse().toString();}
}
输入整型数组和排序标识
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i] = sc.nextInt();}int sortType = sc.nextInt();Arrays.sort(arr);if (sortType == 0) {for (int i : arr) {System.out.print(i + " ");}} else {for (int i = arr.length - 1; i >= 0; i--) {System.out.print(arr[i] + " ");}}}
}
整数与IP地址间的转换
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);while(in.hasNext()){String str = in.next();System.out.println(convert(str));}}private static String convert(String str){//ipv4-->intif(str.contains(".")){String[] fields = str.split("\\.");long result = 0;for(int i=0;i<4;i++){result = result*256+Integer.parseInt(fields[i]);}return ""+result;}else{long ipv4 = Long.parseLong(str);String result = "";for(int i=0;i<4;i++){result = ipv4 % 256 + "."+result;ipv4 /= 256;}return result.substring(0,result.length()-1);}}
}
删除字符串中出现次数最少的字符
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);while (scanner.hasNext()) {String s = scanner.nextLine();char[] chars = s.toCharArray();//统计每个字母的数量HashMap<Character, Integer> map = new HashMap<>();for (char aChar : chars) {map.put(aChar, (map.getOrDefault(aChar, 0) + 1));}//找到数量最少的字符数量Collection<Integer> values = map.values();Integer min = Collections.min(values);//用空字符串替换该字母for (Character character : map.keySet()) {if (map.get(character) == min) {s = s.replaceAll(String.valueOf(character), "");}}System.out.println(s);}}
}
HJ20 密码验证合格程序
import java.util.*;
import java.util.regex.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {String str = sc.next();if (str.length() <= 8) {System.out.println("NG");continue;}if (getMatch(str)) {System.out.println("NG");continue;}if (getString(str, 0, 3)) {System.out.println("NG");continue;}System.out.println("OK");}}// 校验是否有重复子串private static boolean getString(String str, int l, int r) {if (r >= str.length()) {return false;}if (str.substring(r).contains(str.substring(l, r))) {return true;} else {return getString(str, l + 1, r + 1);}}// 检查是否满足正则private static boolean getMatch(String str) {int count = 0;Pattern p1 = Pattern.compile("[A-Z]");if (p1.matcher(str).find()) {count++;}Pattern p2 = Pattern.compile("[a-z]");if (p2.matcher(str).find()) {count++;}Pattern p3 = Pattern.compile("[0-9]");if (p3.matcher(str).find()) {count++;}Pattern p4 = Pattern.compile("[^a-zA-Z0-9]");if (p4.matcher(str).find()) {count++;}if (count >= 3) {return false;} else {return true;}}
}
HJ17 坐标移动
import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNext()) {System.out.println(myAns(in.next()));}}private static String myAns(String str) {int x = 0, y = 0;String[] strs = str.split(";");for (String s : strs) {if ( s == null || s.trim().length() == 0) {continue;}String di = s.substring(0, 1);if (!("A".equals(di) || "D".equals(di) || "W".equals(di) || "S".equals(di)) ) {continue;}int mv = 0;try {mv = Integer.valueOf(s.substring(1));} catch (Exception e) {continue;}if ("A".equals(di)) {x -= mv;} else if ("D".equals(di)) {x += mv;} else if ("W".equals(di)) {y += mv;} else if ("S".equals(di)) {y -= mv;}}return x + "," + y;}
}
跳台阶
import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param number int整型 * @return int整型*/public int jumpFloor (int number) {if(number <=1){return 1;}if(number == 2){return 2;}int[] dp = new int[number+1];dp[0] = 1;dp[1] = 1;dp[2] = 2;for(int i=3;i<=number;i++){dp[i] = dp[i-1]+dp[i-2];}return dp[number];}
}
HJ10 字符个数统计
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别String str = in.next();HashSet<Character> set = new HashSet<>();for(int i=0;i<str.length();i++){set.add(str.charAt(i));}System.out.println(set.size());}
}
HJ3 明明的随机数
import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 获取个数int num = in.nextInt();//去重排序TreeSet<Integer> set = new TreeSet<>();for(int i=0;i<num;i++){set.add(in.nextInt());}Iterator iterator = set.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}
}
进制转换
import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while(in.hasNextLine()){String s = in.nextLine();System.out.println(Integer.parseInt(s.substring(2,s.length()),16));}}
}