坚持最近一个星期把每道题搞熟悉
文章目录
-
- 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-DD
int 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 {} 栈
// check
if(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()){
// 当前字符出现次数向下取偶数,并计入res
int count = kv.getValue();
int rem = count % 2;
res += count - rem;
// 如果当前字符出现次数是奇数,将odd置位1
if(rem == 1){
odd = 1;
}
}
return res+odd;
}
}
859. 亲密字符串
class Solution {
public boolean buddyStrings(String s, String goal) {
//check len
if (s.length() != goal.length()){
return false;
}
// equal
if (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 second
int 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) {
// check
if(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) {
// cache
Map<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) {
// check
if(nums.length <=2){
return nums[nums.length-1];
}
// 排序后中间元素
Arrays.sort(nums);
return nums[nums.length/2];
}
}
53. 最大子数组和
class Solution {
public int maxSubArray(int[] nums) {
//check
if(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);
}
// 拷贝到nums1
System.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;
}
// stack
Deque<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) {
// check
if(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 并且长度不为1
if (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');
}
//数字超过255
if (ans > 255) {
return false;
}
}
return true;
}
public boolean isIPv6(String queryIP) {
String[] split = queryIP.split(":", -1);
//数量不是8
if (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;
}
@Override
public 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) {
//check
if(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) {
// check
if(nums.length==0 || k == 0){
return new int[]{};
}
// hash
Map<Integer,Integer> hash = new HashMap();
for(int i=0;i<nums.length;i++){
hash.put(nums[i],hash.getOrDefault(nums[i],0)+1);
}
// PriorityQueue
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(k,(v1,v2)->{
return hash.get(v1)-hash.get(v2);
});
// offer
for(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);
}
}
}
// res
int[] 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) {
// check
if(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 down
private 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);//up
dfs(heights,atlanticReachable,i,n-1);//down
}
for(int j = 0; j<n;j++){
dfs(heights,pacificReachable,0,j);//left
dfs(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++;
}
}
//如果还有没腐烂的,返回-1
return 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) {
// 设置当前偶数匹配为true
used[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) {
// check
if(s==null || t==null || s.isEmpty() || t.isEmpty() || s.length() < t.length()){
return "";
}
//双map
Map<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()){
//put
char c = s.charAt(right);
if(map.containsKey(c)){
window.put(c,window.getOrDefault(c,0)+1);
//更新count
if(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++) {
// 如果当前元素大于前一个元素,说明连续递增,当前长度加1
if (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;
}
@Override
public int compareTo(Student other) {
// 按成绩排序,成绩相同则按照录入顺序(ArrayList的自然顺序)
if (this.score != other.score) {
return Integer.compare(this.score,other.score);
} else {
return this.name.compareTo(other.name); // 同分情况下,按照姓名字典序
}
}
@Override
public 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 = new
ArrayList<>(); // 创建一个列表来存储输入的区间范围
// 读取输入的区间数据,直到没有更多输入为止
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()) return
Collections.emptyList(); // 如果输入区间为空,直接返回空列表
// 先按照区间的起始位置进行排序
Collections.sort(scopes, Comparator.comparingInt(scope -> scope.start));
List<Scope> result = new
ArrayList<>(); // 创建一个新的列表来存储合并后的区间
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-->int
if(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));
}
}
}