力扣算法实现汇总
- 1.leetcode1.求两数之和-采用哈希查找实现
- 2.LeetCode2_两数相加_java实现
- [3. LeetCode98_验证二叉搜索树(BST)_java实现](#3. LeetCode98_验证二叉搜索树(BST)_java实现)
- [4. LeetCode146_LRU(最近最少使用)缓存_java实现详解](#4. LeetCode146_LRU(最近最少使用)缓存_java实现详解)
- 5.LeetCode148_排序链表_java实现
- 6.LeetCode19_删除链表的倒数第N个结点
- 7.LeetCode24_两两交换链表中的节点_java实现
- 8.LeetCode34_在排序数组中查找元素的第一个和最后一个位置_java实现
- 9.LeetCode11_盛最多水的容器的容器_java实现
- [10. LeetCode15_三数之和_java实现](#10. LeetCode15_三数之和_java实现)
- 11.LeetCode58_最后一个单词的长度_java实现
- [12. LeetCode125_验证回文串_java实现](#12. LeetCode125_验证回文串_java实现)
- [13. LeetCode56_合并区间_java实现](#13. LeetCode56_合并区间_java实现)
- 14.LeetCode189_轮转(翻转)数组_java实现数组_java实现)
- 15.LeetCode322_零钱兑换_java实现
- 16.LeetCode118_杨辉三角_java实现
- 17.LeetCode295_数据流的中位数_java实现
- 18.LeetCode_438_找到字符串中所有字母异位词_java实现
- [19 .LeetCode128_最长连续序列_java实现](#19 .LeetCode128_最长连续序列_java实现)
- 20.LeetCode75_颜色分类_java实现
- 21.LeetCode470_用Rand7()实现Rand10()_java实现
- 22.LeetCode121_买卖股票的最佳时机_java实现
- [23. LeetCode3_无重复字符的最长子串_java实现](#23. LeetCode3_无重复字符的最长子串_java实现)
- [24. LeetCode560_和为k的子数组_java实现](#24. LeetCode560_和为k的子数组_java实现)
- [25. LeetCode53_最大子序和_java实现](#25. LeetCode53_最大子序和_java实现)
- [26. LeetCode509_斐波那契数_动态规划实现](#26. LeetCode509_斐波那契数_动态规划实现)
- 27.Leetcode108_将有序数组转换为二叉搜索树_java实现
- [28. LeetCode543_二叉树的直径_java实现](#28. LeetCode543_二叉树的直径_java实现)
- [29. LeetCode101_对称二叉树_java实现](#29. LeetCode101_对称二叉树_java实现)
- 30.LeetCode226_反转二叉树_java实现
- [31. leetCode144_二叉树的前序遍历_java实现](#31. leetCode144_二叉树的前序遍历_java实现)
- [32. leetcode155_最小栈_java实现](#32. leetcode155_最小栈_java实现)
- [33. LeetCode169_多数元素_java实现](#33. LeetCode169_多数元素_java实现)
- [34. LeetCode35_搜索插入位置_java实现](#34. LeetCode35_搜索插入位置_java实现)
- [35. LeetCode49_字母异位词分组_java实现](#35. LeetCode49_字母异位词分组_java实现)
- 36.leetcode94_二叉树的中序遍历实现
- [37. LeetCode287_寻找重复数_java实现](#37. LeetCode287_寻找重复数_java实现)
- [38. LeetCode20_有效的括号_java多种方法实现](#38. LeetCode20_有效的括号_java多种方法实现)
- 39.leetcode104_二叉树的最大深度java实现
- 40.LeetCode394_字符串解码_java实现
- 41.LeetCode232_用栈实现队列
- 42.LeetCode876_链表的中间节点_java实现
- 43.LeetCode234_回文链表_java实现
- 44.LeetCode142_环形链表II_java实现
- [45. LeetCode160_相交链表_java实现](#45. LeetCode160_相交链表_java实现)
- [46. leetcode141环形链表(链表是否有环)java实现](#46. leetcode141环形链表(链表是否有环)java实现)
- [47. leetCode102_二叉树的层序遍历_java实现](#47. leetCode102_二叉树的层序遍历_java实现)
- [48. LeetCode83_删除排序链表中的重复元素_java实现](#48. LeetCode83_删除排序链表中的重复元素_java实现)
- 49.LeetCode21_合并两个有序链表_java实现
- 50.LeetCode448_找出所有数组中消失的数字_java实现
- 51.LeetCode88_合并有序数组_java实现
- [52. leetcode70_爬楼梯_java多种方法实现](#52. leetcode70_爬楼梯_java多种方法实现)
- [53. leetcode136_只出现一次的数字_java实现](#53. leetcode136_只出现一次的数字_java实现)
- [54. LeetCode283_移动零_Java实现](#54. LeetCode283_移动零_Java实现)
- [55. LeeCode347:前k个高频元素_Java实现](#55. LeeCode347:前k个高频元素_Java实现)
- [56. LeeCode215_数组中的第K个最大元素_java实现](#56. LeeCode215_数组中的第K个最大元素_java实现)
- [57. LeetCode9_回文数_Java实现](#57. LeetCode9_回文数_Java实现)
- 58.leetcode704_二分查找实现
- [59. LeetCode151_反转字符串中的单词java实现](#59. LeetCode151_反转字符串中的单词java实现)
- [60.leetcode_078. 合并K个升序链表.小顶堆实现](#60.leetcode_078. 合并K个升序链表.小顶堆实现)
- [61. leetcode_7:整数反转](#61. leetcode_7:整数反转)
- [62. xx](#62. xx)
1.leetcode1.求两数之和-采用哈希查找实现
java
package com.ag;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* leetcode 1.求两数之和:
* 哈希查找实现
*/
public class TwoSum {
public static int[] twoSUmHashTable(int[]nums,int target){
int size=nums.length;
//辅助哈希表,空间复杂度为O(n)
Map<Integer,Integer> dic=new HashMap<>();
//单层循环,时间复杂度为O(n)
for(int i=0;i<size;i++){
if(dic.containsKey(target-nums[i])){
return new int[]{dic.get(target - nums[i]),i};
}
dic.put(nums[i],i);
}
return new int[0];
}
public static void main(String[] args) {
int[] nums={2,7,11,15};
int[] result=twoSUmHashTable(nums,13);
Arrays.stream(result).forEach(System.out::println);
}
}
2.LeetCode2_两数相加_java实现
java
package com.leetcode;
/**
* LeetCode2_两数相加
*/
public class LeetCode2 {
/**
* 解题思路:将两个链表看成相同长度的进行遍历,
* 如果一个链表较短则在前面补0,eg: 987+23=987+023=1010;
* 如果两个链表全部遍历完毕,进位值为1,则在新链表前方添加节点1
*
* @param l1
* @param l2
* @return
*/
public ListNode14 addTwoNumbers(ListNode14 l1, ListNode14 l2) {
ListNode14 pre = new ListNode14(0);
ListNode14 cur = pre;
int carry = 0;//进位初始化
//1.遍历两个链表
while (l1 != null || l2 != null) {
//2.求解两个链表的和
int x = l1 == null ? 0 : l1.val;
int y = l2 == null ? 0 : l2.val;
int sum = x + y + carry;
carry = sum / 10;//计算进位值
sum = sum % 10;//计算进位之后余数,即实际存入链表
cur.next = new ListNode14(sum);
cur = cur.next;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry == 1) {//如果进位数为1,则在链表前方添加节点1
cur.next = new ListNode14(carry);
}
return pre.next;
}
}
class ListNode14 {
int val;
ListNode14 next;
ListNode14() {
}
ListNode14(int val) {
this.val = val;
}
ListNode14(int val, ListNode14 next) {
this.val = val;
this.next = next;
}
}
3. LeetCode98_验证二叉搜索树(BST)_java实现
java
package com.leetcode;
import java.util.LinkedList;
import java.util.Stack;
/**
* LeetCode98_验证二叉搜索树(BST)
* 解题分析:
* 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
* 有效二叉搜索树定义如下:
* 1.节点的左子树只包含小于当前节点的数;
* 2.节点的右子树只包含大于当前节点的数;
* 3.所有左子树和右子树自身必须也是二叉搜索树。
*/
public class LeetCode98 {
/**
* 方法1:递归实现
*
* @param root
* @return
*/
public boolean isValidBST(TreeNode11 root) {
return recurse(root, null, null);//从根节点开始,上下界都为空
}
/**
* @param node
* @param lower :节点的下界
* @param upper:节点的上届
* @return
*/
private boolean recurse(TreeNode11 node, Integer lower, Integer upper) {
//空节点是合理的二叉搜索树
if (node == null) {
return true;
}
//节点不为空,判断节点上的值是否在上下界内
int val = node.val;
if (lower != null && val <= lower) {
return false;
}
if (upper != null && val >= upper) {
return false;
}
//对子树进行递归
// 将当前节点的值替换为下届,继续检查右边的子节点
if (!recurse(node.right, val, upper)) {
return false;
}
// 将当前节点的值替换为上届,继续检查左边的子节点
if (!recurse(node.left, lower, val)) {
return false;
}
return true; //左右都是二叉树返回true
}
/**
* 方法2:迭代(深度优先搜索)
*
* @param root
* @return
*/
public boolean isValidBST2(TreeNode11 root) {
Integer lower = null, upper = null, val;//初始化上下界都为null
update(root, lower, upper);
while (!stack.isEmpty()) {
//每次从栈中取出一个节点
root = stack.poll();
lower = lowers.poll();
upper = uppers.poll();
if (root == null) {
continue;
}
val = root.val;
//比较上下界之后继续把左子节点和右子节点加入栈
if (lower != null && val <= lower) {
return false;
}
if (upper != null && val >= upper) {
return false;
}
update(root.right, val, upper);
update(root.left, lower, val);
}
return true;
}
/**
* 将当前节点和节点所对应的上下界存入对应的栈中
*
* @param root
* @param lower
* @param upper
*/
private void update(TreeNode11 root, Integer lower, Integer upper) {
stack.add(root);
lowers.add(lower);
uppers.add(upper);
}
//初始化三个栈
LinkedList<TreeNode11> stack = new LinkedList();//用来保存树节点
LinkedList<Integer> uppers = new LinkedList();//用来保存树节点对应的上界
LinkedList<Integer> lowers = new LinkedList();//用来保存树节点对应的下届
/**
* 方法3:中序遍历(左子树->当前节点->右子树)
*
* @param root
* @return
*/
public boolean isValidBST3(TreeNode11 root) {
Stack<TreeNode11> stack = new Stack<>();//存储未访问过的树节点
Integer inorder = null;//存储上一个中序遍历到的树节点的值
while (!stack.isEmpty() || root != null) {
while (root != null) {//不断将root的左子节点加入栈,直到没有剩余的左节点
stack.push(root);
root = root.left;
}
/**
* 将当前子树最左边的节点从stack中取出,
* 比较节点的值是否大于inorder,
* 如果小于等于inorder,则二叉搜索树不合理
*/
root = stack.pop();
if (inorder != null && root.val <= inorder) {
return false;
}
inorder = root.val;//将inorder设为当前节点的值
root = root.right;//将root设为当前节点的右子节点继续循环
}
return true;
}
}
class TreeNode11 {
int val;
TreeNode11 left;
TreeNode11 right;
TreeNode11() {
}
TreeNode11(int val) {
this.val = val;
}
TreeNode11(int val, TreeNode11 left, TreeNode11 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
4. LeetCode146_LRU(最近最少使用)缓存_java实现详解
java
package com.leetcode;
import java.util.LinkedHashMap;
/**
* LeetCode146_LRU(最近最少使用)缓存
* <p>
* LRU是一种缓存策略,按照访问的频率来淘汰。
*/
public class LeetCode146 {
int capacity;//初始化容量
//哈希链表结合了双向链表和哈希表的优点(链表有序,插入快;哈希表查找快);
//从链表的尾部添加元素,最靠近尾部的元素就是最近使用的元素,越靠近头部的元素就是最久未使用的;
LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();
/**
* 初始化LRU缓存容量
*
* @param capacity
*/
public LeetCode146(int capacity) {
this.capacity = capacity;
}
/**
* 根据key返回缓存值,否则返回-1
*
* @param key
* @return
*/
public int get(int key) {
if (!cache.containsKey(key)) {
return -1;
}
//将key变为最近使用
makeRecently(key);
return cache.get(key);
}
/**
* 如果key已经存在,则更新缓存值;
* 不存在则插入key-value;
* 如果插入key-value的值超过capacity,则逐出最久未使用的关键字
*
* @param key
* @param value
*/
public void put(int key, int value) {
//如果key已经存在,修改key对应的值,将key变为最近使用
if (cache.containsKey(key)) {
//修改key的值
cache.put(key, value);
//将key变为最近使用
makeRecently(key);
return;
}
//如果缓存的size大于等于初始化的容量,删除最久没使用的key
if (cache.size() >= this.capacity) {
int oldestKey = cache.keySet().iterator().next();
cache.remove(oldestKey);
}
//将新的key添加链表尾部
cache.put(key, value);
}
private void makeRecently(int key) {
int val = cache.get(key);
//删除key,重新插入队尾
cache.remove(key);
cache.put(key, val);
}
}
5.LeetCode148_排序链表_java实现
java
package com.leetcode;
import java.util.PriorityQueue;
/**
* LeetCode148_排序链表
*/
public class LeetCode148 {
/**
* 小顶堆(优先队列)实现:
* 1.将原链表的每个节点的值依次入堆,元素值会根据从小到大排序;
* 2.创建一个新链表,遍历小顶堆中每个元素创建一个新节点并赋值。
*
* @param head
* @return
*/
public ListNode13 sortList(ListNode13 head) {
if (head == null) {
return null;
}
//1.创建小顶堆
PriorityQueue<Integer> pq = new PriorityQueue<>();
//2.原链表入堆,排序
ListNode13 oldNode = head;//原链表
while (oldNode != null) {
pq.offer(oldNode.val);
oldNode = oldNode.next;
}
//3.遍历小顶堆,创建新链表,
ListNode13 node = new ListNode13(0);
ListNode13 newNode = node;
while (pq.size() > 0) {
node.val = pq.poll();//获取小顶堆值
if (pq.size() > 0) {
ListNode13 temp = new ListNode13(0);
node.next = temp;
}
node = node.next;
}
return newNode;
}
}
class ListNode13 {
int val;
ListNode13 next;
ListNode13() {
}
ListNode13(int val) {
this.val = val;
}
ListNode13(int val, ListNode13 next) {
this.val = val;
this.next = next;
}
}
6.LeetCode19_删除链表的倒数第N个结点
java
package com.leetcode;
import java.util.Stack;
/**
* LeetCode19_删除链表的倒数第N个结点
*/
public class LeetCode19 {
/**
* 实现思路:遍历链表的同时将所有节点依次加入栈,
* 根据栈的先进后出,弹出栈的第n个节点就是要删除的节点,
* 并且当前栈顶的节点就是待删除节点的前驱节点。
*
* @param head
* @param n :倒数第n个节点
* @return
*/
public ListNode11 removeNthFromEnd(ListNode11 head, int n) {
ListNode11 dummy = new ListNode11(0, head);//初始化虚拟节点
//1.遍历链表,将所有节点依次加入栈
Stack<ListNode11> stack = new Stack<>();
ListNode11 cur = dummy;
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
//2.删除第n个元素
for (int i = 0; i < n; i++) {
stack.pop();
}
//3.获取的栈顶的节点为当前待删除节点的前驱节点
ListNode11 prev = stack.peek();
prev.next = prev.next.next;
//4.返回链表的头节点
ListNode11 res = dummy.next;
return res;
}
/**
* 快慢指针:
* 模式识别-涉及链表的特殊位置,考虑快慢指针;要删除链表节点,找到它的前驱
*
* @param head
* @param n
* @return
*/
public ListNode11 removeNthFromEnd2(ListNode11 head, int n) {
ListNode11 dummy = new ListNode11(0, head);//设置虚拟节点
ListNode11 first = head;//定义first为快指针
ListNode11 second = dummy;//定义second为慢指针
//2.使用first对链表进行遍历,遍历次数为n
for (int i = 0; i < n; i++) {
first = first.next;
}
//3.first与second指针对链表进行遍历,当first指针走到链表尾节点,second恰好处于倒数第n个节点
while (first != null) {
first = first.next;
second = second.next;
}
//4.删除第n个节点,调整second.next的指向为second.next.next
second.next = second.next.next;
//5.返回头节点
ListNode11 res = dummy.next;
return res;
}
}
class ListNode11 {
int val;
ListNode11 next;
ListNode11() {
}
ListNode11(int val) {
this.val = val;
}
ListNode11(int val, ListNode11 next) {
this.val = val;
this.next = next;
}
}
7.LeetCode24_两两交换链表中的节点_java实现
java
package com.leetcode;
/**
* LeetCode24_两两交换链表中的节点
*/
public class LeetCode24 {
/**
* 递归解法
* @param head
* @return
*/
public ListNode12 swapPairs(ListNode12 head) {
if(head==null||head.next==null){
return head;
}
ListNode12 next=head.next;
head.next=swapPairs(next.next);
next.next=head;
return next;
}
}
class ListNode12 {
int val;
ListNode12 next;
ListNode12() {
}
ListNode12(int val) {
this.val = val;
}
ListNode12(int val, ListNode12 next) {
this.val = val;
this.next = next;
}
}
8.LeetCode34_在排序数组中查找元素的第一个和最后一个位置_java实现
java
package com.leetcode;
/**
* LeetCode34_在排序数组中查找元素的第一个和最后一个位置
* <p>
* 二分查找的基本思想:在一个区间范围里看处在中间位置的元素的值nums[mid]与目标元素target的大小关系,进而决定目标值落在哪一部分里
*/
public class LeetCode34 {
/**
* 二分查找
*
* @param nums
* @param target
* @return
*/
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
//1.数组长度为0,直接返回未找到位置-1,-1
if (len == 0) {
return new int[]{-1, -1};
}
//2.查找第一个位置
int firstPosition = findFirstPosition(nums, target);
if (firstPosition == -1) {//未找到,返回-1
return new int[]{-1, -1};
}
//2.查找最后一个位置
int lastPosition = findLastPosition(nums, target);
return new int[]{firstPosition, lastPosition};
}
private int findLastPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right + 1) >>> 1;//计算中间位置下标
if (nums[mid] < target) {
//下一轮搜索的区间是[mid+1,right]
left = mid + 1;
} else if (nums[mid] == target) {
//下一轮搜索的区间是[mid,right]
left = mid;
} else {
//nums[mid]>target
//下一轮搜索的区间是[left,mid-1]
right = mid - 1;
}
}
return left;
}
private int findFirstPosition(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right) >>> 1;//计算中间位置下标
if (nums[mid] < target) {
//下一轮搜索的区间是[mid+1,right]
left = mid + 1;
} else if (nums[mid] == target) {
//下一轮搜索的区间是[left,mid]
right = mid;
} else {
//nums[mid]>target
//下一轮搜索的区间是[left,mid-1]
right = mid - 1;
}
}
if (nums[left] == target) {//找到开始位置
return left;
}
return -1;
}
}
9.LeetCode11_盛最多水的容器的容器_java实现

java
package com.leetcode;
/**
* LeetCode11_盛最多水的容器的容器
*/
public class LeetCode11 {
/**
* 解题思路分析:采用双指针
* 设两个指针i,j; 指向水槽的高度分别为h[i],h[j];水槽的面积为为s(i,j).
* 可容纳水的高度由两板中的短板决定,则面积公式为:S(i,j)=min(h[i],h[i]*(j-i))
* <p>
* 移动短板,水槽面积变大;
* 移动长板,水槽面积变小;
*
* @param height
* @return
*/
public int maxArea(int[] height) {
int i = 0, j = height.length - 1, res = 0;
while (i < j) {
res = height[i] < height[j] ? Math.max(res, (j - i) * height[i++]) : Math.max(res, (j - i) * height[j--]);
}
return res;
}
/**
* 双指针
*
* @param height
* @return
*/
public int maxArea2(int[] height) {
int i = 0, j = height.length - 1;//初始化两指针i,j为水槽两端
int res = 0;//初始化结果面积
while (i < j) {
int area = (j - i) * Math.min(height[i], height[j]);//计算水槽面积
res = Math.max(res, area);//更新面积最大值
if (height[i] < height[j]) {//选择短板,向中间收窄
i++;
} else {
j--;
}
}
return res;
}
}
10. LeetCode15_三数之和_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* LeetCode15_三数之和
* <p>
* 解题思路分析:
* 不可以包含重复->识别出可利用排序避免重复答案;
* 利用双指针找到所有解
*/
public class LeetCode15 {
/**
* 排序+双指针解法
*
* @param nums
* @return
*/
public List<List<Integer>> threeSum(int[] nums) {
//1.排序
Arrays.sort(nums);
//存放结果
List<List<Integer>> res = new ArrayList<>();
//遍历数组
for (int i = 0; i < nums.length; i++) {
//2.跳过重复元素
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
//3.采用(双指针)左右指针,目标是找到nums[left]+nums[right]=-nums[i]
int left = i + 1, right = nums.length - 1;
int target = -nums[i];
while (left < right) {
//两数之和
int sum = nums[left] + nums[right];
if (sum == target) {
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
left++;
right--;
//跳过重复元素
while (left < right && nums[left] == nums[left - 1]) {
left++;
}
while (left < right && nums[right] == nums[right + 1]) {
right--;
}
} else if (sum < target) {
left++;
} else {
right--;
}
}
}
return res;
}
}
11.LeetCode58_最后一个单词的长度_java实现
java
package com.leetcode;
/**
* LeetCode58_最后一个单词的长度
*/
public class LeetCode58 {
/**
* 解法:采用反向遍历
*
* @param s
* @return
*/
public int lengthOfLastWord(String s) {
int end = s.length() - 1;
while (end >= 0 && s.charAt(end) == ' ') {//1.先从尾部过滤掉空格
end--;
}
if (end < 0) {
return 0;
}
int start = end;
while (start >= 0 && s.charAt(start) != ' ') {//2.从尾部向前遍历,找到单词头部
start--;
}
return end - start; //3.两者相减为单词长度
}
}
12. LeetCode125_验证回文串_java实现
java
package com.leetcode;
/**
* LeetCode125_验证回文串
*/
public class LeetCode125 {
/**
* 方法1:筛选+比较
*
* @param s
* @return
*/
public boolean isPalindrome(String s) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (Character.isLetterOrDigit(ch)) {//判断是字母或数字
sb.append(Character.toLowerCase(ch));
}
}
String oldStr = sb.toString();
String strReverse = sb.reverse().toString();
if (oldStr.equals(strReverse)) {//比较原生字符串与翻转之后字符串是否相等
return true;
} else {
return false;
}
}
/**
* 方法2:采用双指针
*
* @param s
* @return
*/
public boolean isPalindrome2(String s) {
StringBuffer sb = new StringBuffer();
//1.转换字符串为符合规则的字母或字母串
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (Character.isLetterOrDigit(ch)) {
sb.append(Character.toLowerCase(ch));
}
}
//定义左右指针left,right
int left = 0, right = sb.length() - 1;
while (left < right) {
if (sb.charAt(left) != sb.charAt(right)) {
return false;
}
//left,与right指针相向移动
left++;
right--;
}
return true;
}
}
13. LeetCode56_合并区间_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* LeetCode56_合并区间
*/
public class LeetCode56 {
/**
* 按照左端点排序后的,合并区间一定是intervals中的连续子数组
*
* @param intervals
* @return
*/
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (p, q) -> p[0] - q[0]);//按照左端点从小到右排序
List<int[]> res = new ArrayList<>();
for (int[] p : intervals) {
int m = res.size();
if (m > 0 && p[0] <= res.get(m - 1)[1]) {//相交,可以合并
res.get(m - 1)[1] = Math.max(res.get(m - 1)[1], p[1]);//更新右端点最大值
} else {//不相交,无法合并
res.add(p);//新的合并区间
}
}
return res.toArray(new int[res.size()][]);
}
}
14.LeetCode189_轮转(翻转)数组_java实现
java
package com.leetcode;
/**
* LeetCode189_轮转(翻转)数组
*/
public class LeetCode189 {
public void rotate(int[] nums, int k) {
int length = nums.length;
k %= length;
// 1.反转全部元素
reverse(nums, 0, length - 1);
// 2.反转前k个元素
reverse(nums, 0, k - 1);
// 3.反转剩余的
reverse(nums, k, length - 1);
}
/**
* 把数组中从【start,end】之间的元素两辆交互,也就是反转
*
* @param nums
* @param start
* @param end
*/
private void reverse(int[] nums, int start, int end) {
// TODO Auto-generated method stub
while (start < end) {
int temp = nums[start];
nums[start++] = nums[end];
nums[end--] = temp;
}
}
}
15.LeetCode322_零钱兑换_java实现
java
package com.leetcode;
import java.util.Arrays;
/**
* LeetCode322_零钱兑换
* 问题分析:兑换零钱,是一个完全背包问题:
* 硬币总金额有限场景下;
* 每个硬币可以无限次使用;
* 硬币组合是与顺序无关,使用最少的硬币个数凑成总金额问题;
*/
public class LeetCode322 {
/**
* @param coins 可选的钱币面值
* @param amount 总金额
* @return
*/
public static int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];//1.定义dp表
Arrays.fill(dp, amount + 1);
dp[0] = 0;
//2.外层循环先遍历的是硬币面值,内层循环遍历的是面值总和
for (int coin : coins) {
for (int i = coin; i <= amount; i++) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1);//3.状态转移公式
}
}
if (dp[amount] == amount + 1) {
dp[amount] = -1;
}
return dp[amount];//4.返回结果
}
public static void main(String[] args) {
// int[]coins={1,2,5};
// System.out.println(coinChange(coins,11));
// int[]coins={2};
// System.out.println(coinChange(coins,3));
int[] coins = {1};
System.out.println(coinChange(coins, 0));
}
}
16.LeetCode118_杨辉三角_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.List;
/**
* LeetCode118_杨辉三角
*/
public class LeetCode118 {
/**
* 动态规划实现
*
* 在「杨辉三角」中,每个数是它左上方和右上方的数的和
*
* @param numRows:行数
* @return
*/
public static List<List<Integer>> generate2(int numRows) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
for (int i = 0; i < numRows; ++i) {
List<Integer> row = new ArrayList<>();
for (int j = 0; j <= i; ++j) {
if (j == 0 || j == i) {// 第0列或第1列,求和值为1
row.add(1);
} else {
row.add(res.get(i - 1).get(j - 1) + res.get(i - 1).get(j));// 每个数是它左上方和右上方的数的和
}
}
res.add(row);// 添加每一行的值
}
return res;// 返回结果
}
public static void main(String[] args) {
System.out.println("res:" + generate2(5));
}
}
17.LeetCode295_数据流的中位数_java实现
java
package com.leetcode;
import java.util.PriorityQueue;
import java.util.Queue;
/**
* LeetCode295_数据流的中位数
*
* 解题思路:借助堆对元素进行排序,小顶堆a和大顶堆b各自保存列表一半的元素; a存储较大的一半,b存储较小的一半
*/
public class LeetCode295 {
Queue<Integer> a;// 定义小顶堆,保存较大的一半
Queue<Integer> b;// 定义大顶堆,保存较小的一半
public LeetCode295() {
a = new PriorityQueue<>();
b = new PriorityQueue<>((x, y) -> (y - x));
}
/**
* 1.对添加的元素排序
*
* @param num
*/
public void addNum(int num) {
if (a.size() != b.size()) {
a.add(num);
b.add(a.poll());// 存放小顶堆a中堆顶元素
} else {
b.add(num);
a.add(b.poll());// 存放大顶堆b中堆顶元素
}
}
/**
* 2.返回中位元素
*
* 当小顶堆a中元素个数与大顶堆b中元素个数不相同时候,中位数为a中的堆顶元素;
* 当小顶堆a中元素个数与大顶堆b中元素个数相同时候,中位数为(a的堆顶元素+b的堆顶元素)/2
*
* @return
*/
public double findMedian() {
return a.size() != b.size() ? a.peek() : (a.peek() + b.peek()) / 2.0;
}
}
18.LeetCode_438_找到字符串中所有字母异位词_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.List;
/**
* LeetCode_438_找到字符串中所有字母异位词
*/
public class LeetCode_438 {
/**
* 解题思路:滑动窗口+左右索引指针
*
* @param s
* @param p
* @return
*/
public List<Integer> findAnagrams(String s, String p) {
char[] arrS = s.toCharArray();
char[] arrP = p.toCharArray();
// 1.存放最终返回结果
List<Integer> res = new ArrayList<>();
// 2.
// 定义一个needs(记录需要得到的元素)数组来看arrP中包含元素的个数
int[] needs = new int[26];
// 定义一个window(滑动窗口遍历到的元素)数组来看滑动窗口中是否有arrP中的元素,并记录出现的个数
int[] window = new int[26];
// 3.将arrp中的元素保存到needs数组中,
// 然后通过不断移动滑动窗口,将目标元素的个数保存到window中
for (int i = 0; i < arrP.length; i++) {
needs[arrP[i] - 'a'] += 1;
}
// 定义滑动窗口的两端
int left = 0;
int right = 0;
// 右窗口开始不断向右移动
while (right < arrS.length) {
int curR = arrS[right] - 'a';
right++;
// 将右窗口当前访问到的元素curR个数加1
window[curR] += 1;
// 当window数组curR比needs数组中对应元素的个数要多的时候,移动左窗口指针,减少多余的个数
while (window[curR] > needs[curR]) {
int curL = arrS[left] - 'a';
left++;
// 将左窗口当前访问到的元素curL个数减1
window[curL] -= 1;
}
// 4.将所有符合要求的左窗口索引放到结果res中
if (right - left == arrP.length) {
res.add(left);
}
}
return res;
}
}
19 .LeetCode128_最长连续序列_java实现
java
package com.leetcode;
import java.util.HashSet;
import java.util.Set;
/**
* LeetCode128_最长连续序列
*/
public class LeetCode128 {
/**
* 哈希表实现
*
* @param nums
* @return
*/
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
// 1. set去重
for (int num : nums) {
set.add(num);
}
int longestStreak = 0;// 最长序列长度
// 2.遍历
for (Integer num : set) {
if (!set.contains(num - 1)) {// 不在集合set中,更新序列长度
int currentNum = num;
int currentStreak = 1;// 当前序列长度
while (set.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
// 更新序列长度
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;// 返回最长序列长度
}
}
20.LeetCode75_颜色分类_java实现
java
package com.leetcode;
/**
* LeetCode75_颜色分类
*/
public class LeetCode75 {
/**
* 双指针,一次遍历
*
* @param nums
*/
public static void sortColors(int[] nums) {
int n0 = 0, n1 = 0;
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
nums[i] = 2;
if (num < 2) {
nums[n1++] = 1;
}
if (num < 1) {
nums[n0++] = 0;
}
}
}
}
21.LeetCode470_用Rand7()实现Rand10()_java实现
java
/**
* LeetCode470_用Rand7()实现Rand10()
*/
public class LeetCode470 extends SolBase {
public int rand10() {
int temp = 40;
while (temp >= 40) {
temp = (rand7() - 1) * 7 + rand7() - 1;
}
return temp % 10 + 1;
}
}
解题思路分析过程:

22.LeetCode121_买卖股票的最佳时机_java实现
java
package com.leetcode;
/**
* LeetCode121_买卖股票的最佳时机
*/
public class LeetCode121 {
/**
* 动态规划的实现
*
* @param prices
* @return
*/
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
int[][] dp = new int[len][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
// 从第二天开始遍历
for (int i = 1; i < len; i++) {
// 0:没持股;1:表示持股
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = Math.max(dp[i - 1][1], -prices[i]);
}
return dp[len - 1][0];
}
public int maxProfit2(int[] prices) {
if (prices.length < 2) {
return 0;
}
int profitMax = 0;// 最大差距
int min = prices[0];
for (int i = 0; i < prices.length; ++i) {
if (prices[i] > min) {
// 当前元素大于当前最小值,看是否需要更新已知的最大差距
profitMax = Math.max(profitMax, prices[i] - min);
} else {
// 当前元素小于等于当前最小值,更新当前最小值
min = prices[i];
}
}
return profitMax;
}
}
23. LeetCode3_无重复字符的最长子串_java实现
java
package com.leetcode;
import java.util.HashSet;
import java.util.Set;
/**
* LeetCode3_无重复字符的最长子串
*
*
* 解题思路: 无重复字符->出现1次,涉及出现次数,使用hashset; 涉及子串,采用采用滑动窗口
*/
public class LeetCode3 {
public static int lengthOfLongestSubstring(String s) {
char[] chars = s.toCharArray();
Set<Character> set = new HashSet<>();// 去重
int res = 0;// 存放结果
for (int left = 0, right = 0; right < s.length(); right++) {// 每一次循环,右端点都扩展一个
char ch = chars[right];// right指向的元素
while (set.contains(ch)) {// set中有ch,则缩短左边界,同时从集合中出元素
set.remove(chars[left]);
left++;
}
set.add(chars[right]);// 没有重复则将当前元素加入set
res = Math.max(res, right - left + 1);// 计算当前不重复子串的长度
}
return res;
}
public static void main(String[] args) {
String s = "abcabcbb";
System.out.println("length:" + lengthOfLongestSubstring(s));
String s2 = "pwwkew";
System.out.println("length:" + lengthOfLongestSubstring(s2));
String s3 = "bbbbb";
System.out.println("length:" + lengthOfLongestSubstring(s3));
}
}
24. LeetCode560_和为k的子数组_java实现
java
package com.leetcode;
import java.util.HashMap;
/**
* LeetCode560_和为k的子数组
*/
public class LeetCode560 {
/**
* 解题方法:采用前缀和+哈希表优化
*
*
* pre[i]=pre[i-1]+nums[i]; [j..i] 个子数组和为 k 这个条件以转化为pre[i]−pre[j−1]==k
*
* 则推导出:pre[j−1]==pre[i]−k
*
* @param nums
* @param k
* @return
*/
public int subarraySum(int[] nums, int k) {
int count = 0;// 统计子数组个数
int pre = 0;// 存放前缀和
HashMap<Integer, Integer> mp = new HashMap<>();
mp.put(0, 1);// key存放num,value存放count值
for (int i = 0; i < nums.length; i++) {
pre += nums[i];
if (mp.containsKey(pre - k)) {
count += mp.get(pre - k);
}
mp.put(pre, mp.getOrDefault(pre, 0) + 1);// 子数组和不存在,累加1
}
return count;
}
}
25. LeetCode53_最大子序和_java实现
java
package com.leetcode;
/**
* LeetCode53_最大子序和
*/
public class LeetCode53 {
/**
* 动态规划实现
*
* @param nums
* @return
*/
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
// 初始化dp数组
dp[0] = nums[0];
// dp数组
int result = dp[0];
for (int i = 1; i < nums.length; i++) {
// 状态转移公式
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
// result保存dp[i]的最大值
if (dp[i] > result)
result = dp[i];
}
return result;
}
/**
* 动态规划实现,不需要dp数组
*
* @param nums
* @return
*/
public int maxSubArray2(int[] nums) {
int result = nums[0];
int pre = result;
for (int i = 1; i < nums.length; i++) {
pre = Math.max(pre + nums[i], nums[i]);
if (pre > result)
result = pre;
}
return result;
}
}
26. LeetCode509_斐波那契数_动态规划实现
java
package com.leetcode;
/**
* LeetCode509:斐波那契数
*
* 实现思路:采用动态规划实现
*/
public class LeetCode509 {
public int fib(int n) {
if (n <= 1)
return n;
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
27.Leetcode108_将有序数组转换为二叉搜索树_java实现
java
package com.leetcode;
/**
* Leetcode108:将有序数组转换为二叉搜索树
*
* 高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1
*
* 解题思路:以升序序列中的任一个元素作为根节点,以该元素左边的升序序列构建左子树, 以该元素右边的升序序列构建右子树,得到的树就是一棵二叉搜索树;
* 本题要求高度平衡,需要选择升序序列的中间元素作为根节点;
*/
public class Leetcode108 {
/**
* 递归解法
*
* 解题要点: 二叉搜索树(BST); 二叉搜索树定义; 模式识别:树通常具有子结构,一旦涉及解决子问题,考虑用递归解法
*
* BST的中序遍历是升序的,本题等于根据中序遍历的序列恢复二叉搜索树
*
* @param nums
* @return
*/
public TreeNode9 sortedArrayToBST(int[] nums) {
return dfs(nums, 0, nums.length - 1);
}
private TreeNode9 dfs(int[] nums, int lo, int hi) {
// TODO Auto-generated method stub
if (lo > hi) {
return null;
}
// 以升序数组的中间元素作为根节点
int mid = lo + (hi - lo) / 2;
TreeNode9 root = new TreeNode9(nums[mid]);
// 递归的构建root的左子树和右子树
root.left = dfs(nums, lo, mid - 1);
root.right = dfs(nums, mid + 1, hi);
return root;
}
}
class TreeNode9 {
int val;
TreeNode9 left;
TreeNode9 right;
TreeNode9() {
}
TreeNode9(int val) {
this.val = val;
}
TreeNode9(int val, TreeNode9 left, TreeNode9 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
28. LeetCode543_二叉树的直径_java实现
java
package com.leetcode;
/**
* LeetCode543:二叉树的直径
*
* 二叉树的直径是指树中任意两个节点之间最长路径的长度。这条路径有可能不经过根节点root
*
* 两个节点之间路径的长度由他们之间边数表示
*
* 两个叶子节点之间路径=根节点左右儿子的深度之和
*/
public class LeetCode543 {
int ans;// 记录节点的最大值
/**
* 采用深度优先(大多使用递归函数)实现
*
* @param root
* @return
*/
public int diameterOfBinaryTree(TreeNode8 root) {
ans = 1;
depth(root);
return ans - 1;// 节点数减1为二叉树的直径
}
private int depth(TreeNode8 node) {
if (node == null) {
return 0;// 访问到空节点,返回0;
}
int left = depth(node.left);// 左儿子为根的子树的深度
int right = depth(node.right);// 右儿子为根的子树的深度
ans = Math.max(ans, left + right + 1);// 该节点为根的子树的深度,更新ans
return Math.max(left, right) + 1;// 返回该节点为根的子树的深度
}
}
class TreeNode8 {
int val;
TreeNode8 left;
TreeNode8 right;
TreeNode8() {
}
TreeNode8(int val) {
this.val = val;
}
TreeNode8(int val, TreeNode8 left, TreeNode8 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
29. LeetCode101_对称二叉树_java实现
java
package com.leetcode;
import java.util.LinkedList;
import java.util.Queue;
/**
* LeetCode101:对称二叉树
*/
public class LeetCode101 {
/**
* 实现思路:递归判断一个树的左节点的左孩子与右节点的右孩子是否相等
*
* @param root
* @return
*/
public boolean isSymmetric(TreeNode7 root) {
if (root == null) {
return true;
}
// 调用递归函数,比较左节点,右节点
return deepCheck(root.left, root.right);
}
private boolean deepCheck(TreeNode7 left, TreeNode7 right) {
// 递归的终止条件是两个节点都为空; 或者 两个节点中右一个为空;或者两个节点的值不相等
if (left == null && right == null) {
return true;// 对称
}
if (left == null || right == null) {
return false;// 不对称
}
if (left.val != right.val) {
return false;// 不对称
}
// 再递归的比较 左节点的左孩子和右节点的右孩子
// 以及比较左节点的右孩子和右节点的左孩子
return deepCheck(left.left, right.right) && deepCheck(left.right, right.left);
}
/**
* 实现思路:采用队列,让左节点的左孩子,右节点的右孩子入队,然后遍历出队比较检查
*
* @param root
* @return
*/
public boolean isSymmetric2(TreeNode7 root) {
Queue<TreeNode7> queue = new LinkedList<>();
TreeNode7 l = root.left;
TreeNode7 r = root.right;
if (root == null || (l == null && r == null)) {
return true;// 对称
}
// 入队
queue.offer(l);
queue.offer(r);
while (!queue.isEmpty()) {
l = queue.poll();
r = queue.poll();
if (l == null && r == null) {
continue;
}
if (l == null || r == null || (l.val != r.val)) {
return false;// 不对称
}
// 左节点的左孩子,右节点的右孩子入队
queue.offer(l.left);
queue.offer(r.right);
// 左节点的右孩子,右节点的左孩子入队
queue.offer(l.right);
queue.offer(r.left);
}
return true;
}
}
class TreeNode7 {
int val;
TreeNode7 left;
TreeNode7 right;
TreeNode7() {
}
TreeNode7(int val) {
this.val = val;
}
TreeNode7(int val, TreeNode7 left, TreeNode7 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
30.LeetCode226_反转二叉树_java实现
java
package com.leetcode;
/**
* LeetCode226:反转二叉树
*/
public class LeetCode226 {
/**
* 采用递归
* @param root
* @return
*/
public TreeNode6 invertTree(TreeNode6 root) {
if (root == null) {
return null;
}
invertTree(root.left);
invertTree(root.right);
TreeNode6 temp=root.left;
root.left=root.right;
root.right=temp;
return root;
}
}
class TreeNode6 {
int val;
TreeNode6 left;
TreeNode6 right;
TreeNode6() {
}
TreeNode6(int val) {
this.val = val;
}
TreeNode6(int val, TreeNode6 left, TreeNode6 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
31. leetCode144_二叉树的前序遍历_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* leetCode144:二叉树的前序遍历
*/
public class LeetCode144 {
/**
* 前序遍历-递归实现
*
* @param root
* @return
*/
public List<Integer> preorderTraversal(TreeNode5 root) {
List<Integer> res = new ArrayList<>();
accessTree(root, res);
return res;
}
public void accessTree(TreeNode5 root, List<Integer> res) {
if (root == null) {
return;
}
res.add(root.val);
accessTree(root.left, res);
accessTree(root.right, res);
}
/**
* 前序遍历-利用栈实现遍历
* @param root
* @return
*/
public List<Integer> preorderTraversal2(TreeNode5 root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode5> stack = new LinkedList<>();
while (!stack.isEmpty() || root != null) {
while (root != null) {
res.add(root.val);
stack.push(root);
root = root.left;
}
root = stack.pop();
root = root.right;
}
return res;
}
}
class TreeNode5 {
int val;
TreeNode5 left;
TreeNode5 right;
TreeNode5() {
}
TreeNode5(int val) {
this.val = val;
}
TreeNode5(int val, TreeNode5 left, TreeNode5 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
32. leetcode155_最小栈_java实现
java
package com.leetcode;
import java.util.Stack;
/**
* LeetCode155:最小栈
*
* 思路:辅助栈
*
* 定义一个数据栈,支持push,pop,top 定义一个辅助栈,其栈顶为当前的最小值,以支持常数时间复杂度的getMin操作
*/
public class LeetCode155 {
Stack<Integer> dataStack;// 定义数据栈
Stack<Integer> minStack;// 定义辅助栈
/**
* 初始化堆栈对象
*/
public LeetCode155() {
dataStack = new Stack<>();
minStack = new Stack<>();
}
/**
* 将元素val推入堆栈
*
* @param val
*/
public void push(int val) {
dataStack.push(val);
if (minStack.isEmpty() || val <= minStack.peek()) {// push操作时,需要保持minStack的栈顶为当前的最小值。
minStack.push(val);
}
}
/**
* 删除堆栈顶部的元素
*/
public void pop() {
// 如果pop的元素是当前的最小值,则需要将minStack的栈顶元素也pop出
int val = dataStack.pop();
if (val == minStack.peek()) {
minStack.pop();
}
}
/**
* 获取堆栈顶部的元素
*
* @return
*/
public int top() {
return dataStack.peek();// 返回数据栈的栈顶元素
}
/**
* 获取堆栈中的最小元素
*
* @return
*/
public int getMin() {
return minStack.peek();// 返回辅助栈的栈顶元素
}
}
33. LeetCode169_多数元素_java实现
java
package com.leetcode;
import java.util.Arrays;
/**
* LeetCode169:多数元素
*/
public class LeetCode169 {
/**
* 方法1:排序,计算过半元素下标
*
* @param nums
* @return
*/
public static int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
public static void main(String[] args) {
int[] nums = { 3, 2, 3 };
System.out.println("res:" + majorityElement(nums));
int[] nums2 = { 2, 2, 1, 1, 1, 2, 2 };
System.out.println("res:" + majorityElement(nums2));
}
}
34. LeetCode35_搜索插入位置_java实现
java
package com.leetcode;
/**
* LeetCode35:搜索插入位置
*
* 解题思路:二分查找(如果是一个问题,带查找的数是整数,且知道范围,可用二分查找算法)
*
* 二分查找算法: 1.先设定左侧下标和右侧下标right,再计算中间下标mid
* 2.每次根据nums[mid]和target之间的大小进行判断,相等则直接返回下标, nums[mid]<target 则右移,
* nums[mid]>target 则 right 左移
*
* 3.查找结束如果没有相等值则返回left,该值为插入位置
*
*/
public class LeetCode35 {
public static int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (right + left) / 2;
if (target == nums[mid]) {
return mid;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
public static void main(String[] args) {
int[] nums = { 1, 3, 5, 6 };
System.out.println("###:" + searchInsert(nums, 2));
}
}
35. LeetCode49_字母异位词分组_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* LeetCode49:字母异位词分组
*
* 字母异位词是指字母相同,但排列不同的字符串
*
* eg: strs=["are","bat","ear","code","tab","era"]
*
* ans={"aer":["are","ear","era"], "abt":["bat","tab"], "ecdo":["code"] }
*
* 模式识别:一旦需要根据特征进行归类,就应该利用散列表
*/
public class LeetCode49 {
/**
* 方法1:字母排序
*
* @param strs
* @return
*/
public List<List<String>> groupAnagrams(String[] strs) {
if (strs.length == 0)
return new ArrayList<>();
Map<String, List<String>> ans = new HashMap<>();
for (String s : strs) {
char[] ca = s.toCharArray();
Arrays.sort(ca);
String key = String.valueOf(ca);
if (!ans.containsKey(key)) {
ans.put(key, new ArrayList<>());
}
ans.get(key).add(s);
}
return new ArrayList<>(ans.values());
}
/**
* 方法2:字符统计
*
* @param strs
* @return
*/
public List<List<String>> groupAnagrams2(String[] strs) {
if (strs.length == 0)
return new ArrayList<>();
Map<String, List<String>> ans = new HashMap<>();
int[] count = new int[26];
for (String s : strs) {
// 统计字符的出现次数
Arrays.fill(count, 0);
for (char c : s.toCharArray()) {
count[c - 'a']++;
}
// 构造特征键()字符串
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < 26; i++) {
sb.append('#');
sb.append(count[i]);
}
// 具有相同特征字符串的单词放在一组
String key = sb.toString();
if (!ans.containsKey(key)) {
ans.put(key, new ArrayList<>());
}
ans.get(key).add(s);
}
return new ArrayList<>(ans.values());// 返回结果
}
}
36.leetcode94_二叉树的中序遍历实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* LeetCode94:二叉树的中序遍历
*/
public class LeetCode94 {
/**
* 采用stack实现二叉树的中序遍历
*
* @param root
* @return
*/
public List<Integer> inOrderTraversalWithLoop(TreeNode4 root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode4> stack = new LinkedList<>();// 创建栈
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
return res;
}
/**
* 中序遍历_递归遍历实现
*
* @param root
* @return
*/
public List<Integer> inorderTraversal(TreeNode4 root) {
List<Integer> list = new ArrayList<>();
inOrder(list, root);
return list;
}
public void inOrder(List<Integer> list, TreeNode4 root) {
if (root == null) {
return;
}
inOrder(list, root.left);
list.add(root.val);
inOrder(list, root.right);
}
}
class TreeNode4 {
int val;
TreeNode4 left;
TreeNode4 right;
TreeNode4() {
}
TreeNode4(int val) {
this.val = val;
}
TreeNode4(int val, TreeNode4 left, TreeNode4 right) {
this.val = val;
this.left = left;
this.right = right;
}
}
37. LeetCode287_寻找重复数_java实现
java
package com.leetcode;
/**
* LeetCode287:寻找重复数
*
* 解题思路:判断链表是否有环;采用快慢指针(慢指针每次前进一步,快指针每次前进两步),判断是否存在环
*/
public class LeetCode287 {
/**
* / 方法:在数组中找到链表中环的起始节点(即重复元素)
*
* @param nums
* @return
*/
public static int findDuplicate(int[] nums) {
// 慢指针每次前进一步,快指针每次前进两步
int slow = nums[0];
int fast = nums[nums[0]];
// 使用快慢指针查找,链表中的环(数组中的重复元素)
while (slow != fast) {
slow = nums[slow];// 慢指针前进一步
fast = nums[nums[fast]];// 快指针前进两步
}
slow = 0;
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
public static void main(String[] args) {
int[] nums = { 1, 3, 4, 2, 2 };
System.out.println("findDuplicate:" + findDuplicate(nums));
int[] nums2 = { 3, 4, 3, 1, 2 };
System.out.println("findDuplicate:" + findDuplicate(nums2));
int[] nums3 = { 3, 3, 3, 3, 3 };
System.out.println("findDuplicate:" + findDuplicate(nums3));
}
}
38. LeetCode20_有效的括号_java多种方法实现
java
package com.leetcode;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
/**
* LeetCode20:有效的括号
*
* 解题思路:括号匹配是采用栈解决的经典问题
*/
public class LeetCode20 {
/**
* 解题思路:先出现的左括号,后匹配; 模式识别:先进后出采用栈
* @param s
* @return
*/
public static boolean isValid1(String s) {
Stack<Character> statck=new Stack<>();
char ch;
for(int i=0;i<s.length();i++) {
ch=s.charAt(i);
if(ch=='(') {
statck.push(')');
}else if(ch=='{') {
statck.push('}');
}else if(ch=='[') {
statck.push(']');
}else if(statck.isEmpty()||statck.peek()!=ch) {
return false;
}else {//如果是右括号判断是否和栈顶元素匹配
statck.pop();
}
}
//最后判断栈中元素是否匹配
return statck.isEmpty();
}
public static boolean isValid2(String s) {
if(s.length()==0) {
return true;//字符串为空返回true
}
Stack<Character> statck=new Stack<>();
char curCh;
for(int i=0;i<s.length();i++) {
curCh=s.charAt(i);
if(curCh=='}'||curCh==']'||curCh==')') {
if(statck.empty()||!isMatch(statck.peek(), curCh)) {
return false;
}else {
statck.pop();//括号匹配则删除
}
}else {
statck.push(curCh);//当前字符与右括号不配配,则添加当前括号到栈中
}
}
return statck.empty();
}
/**
* 判断括号是否匹配
* @param left
* @param right
* @return
*/
private static boolean isMatch(Character left,Character right) {
switch (right) {
case ')':
return left=='(';
case ']':
return left=='[';
case '}':
return left=='{';
default:
return false;
}
}
public static boolean isValid3(String s) {
//1.有效字符串的长度一定为偶数,如果字符串的长度为奇数,则返回false,省去后面的遍历判断
int n=s.length();
if(n%2==1) {
return false;
}
//2.判断括号的匹配类型,采用hash
Map<Character, Character> pairs=new HashMap<>();
pairs.put(')', '(');
pairs.put(']', '[');
pairs.put('}', '{');
//3.遍历字符串,判断匹配情况
Stack<Character> stack=new Stack<>();
for(int i=0;i<n;i++) {
char ch=s.charAt(i);
if(pairs.containsKey(ch)) {
if(stack.isEmpty()||stack.peek()!=pairs.get(ch)) {
return false;
}
stack.pop();//匹配删除括号
}else {
stack.push(ch);//不匹配添加进栈
}
}
return stack.isEmpty();//栈为空,说明全部匹配了
}
public static void main(String[] args) {
String s1="()";
System.out.println("isValid(s1):"+isValid3(s1));
String s2="()[]{}";
System.out.println("isValid(s2):"+isValid3(s2));
String s3="(]";
System.out.println("isValid(s1):"+isValid3(s3));
String s4="([)]";
System.out.println("isValid(s1):"+isValid3(s4));
String s5="{[]}";
System.out.println("isValid(s1):"+isValid3(s5));
}
}
39.leetcode104_二叉树的最大深度java实现
java
package com.leetcode;
import java.util.LinkedList;
import java.util.Queue;
/**
* leetCode104:二叉树的最大深度
*
*
* 二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数
*/
public class LeetCode104 {
/**
* 方法1采用递归(深度优先搜索)
*
* 思路:知道二叉树的左子树与右子树的最大深度为l和r,则二叉树的最大深度为max(l,r)+1
* @param root
* @return
*/
public int maxDepth1(TreeNode root) {
if(root==null) {
return 0;
}
return 1+Math.max(maxDepth1(root.left), maxDepth1(root.right));
}
/**
* 树的深度(DFS)遍历实现
* @param root
* @return
*/
public int maxDepth4(TreeNode root){
if(root==null){
return 0;
}
int left=maxDepth4(root.left);
int right=maxDepth4(root.right);
int max_depth=Math.max(left,right)+1;;
return max_depth;
}
/**
* 方法2:采用迭代BSF(广度优先搜索)
* @param root
* @return
*/
public int maxDepth2(TreeNode root) {
if(root==null) {
return 0;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
int res=0;//层数结果即二叉树的深度
while(!queue.isEmpty()) {
int size=queue.size();
while(size-->0) {
TreeNode node=queue.poll();
if(node.left!=null) {
queue.offer(node.left);
}
if(node.right!=null) {
queue.offer(node.right);
}
}
res++; //遍历完一层加1
}
return res;
}
/**
* 树的层序遍历,计算最大深度
*
* @param root
* @return
*/
public int maxDepth3(TreeNode root) {
if (root == null) {
return 0;
}
int depth = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {//遍历每层的节点
TreeNode cur = queue.poll();
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
}
depth++;//统计层数
}
return depth;
}
}
class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode() {
// TODO Auto-generated constructor stub
}
TreeNode(int val){
this.val=val;
}
TreeNode(int val,TreeNode left, TreeNode right){
this.val=val;
this.left=left;
this.right=right;
}
}
40.LeetCode394_字符串解码_java实现
java
package com.leetcode;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Stack;
/**
* LeetCode394:字符串解码
* <p>
* 解题思路:
* 采用栈实现;
* 元组:数字[字符串]
*/
public class LeetCode394 {
int ptr;
/**
* 思路1.基于linkedList
*
* @param s
* @return
*/
public String decodeString(String s) {
LinkedList<String> stk = new LinkedList<>();//定义栈
ptr = 0;
while (ptr < s.length()) {
char cur = s.charAt(ptr);
if (Character.isDigit(cur)) {//处理数字,使数字完整
String digits = getDigit(s);
stk.addLast(digits);
} else if (Character.isLetter(cur) || cur == '[') {//处理普通字符和"["
stk.addLast(String.valueOf(s.charAt(ptr++)));
} else {//遇见"]",处理匹配的"["之间的字符
++ptr;
LinkedList<String> sub = new LinkedList<>();
while (!"[".equals(stk.peekLast())) {
sub.addLast(stk.removeLast());
}
//因为栈的特点,导致组合的字符串和原本的字符串相比是倒序的,因此需要翻转一次
Collections.reverse(sub);
//左括号出栈
stk.removeLast();
//此时栈顶为当前sub对应的字符串应该出现的次数
int repTime = Integer.parseInt(stk.removeLast());
StringBuffer t = new StringBuffer();
String o = getString(sub);
//构造字符串
while (repTime-- > 0) {
t.append(o);
}
//构造好字符串入栈
stk.addLast(t.toString());
}
}
return getString(stk);
}
private String getString(LinkedList<String> v) {
StringBuffer ret = new StringBuffer();
for (String s : v) {
ret.append(s);
}
return ret.toString();
}
private String getDigit(String s) {
StringBuffer ret = new StringBuffer();
//拼凑数字
while (Character.isDigit(s.charAt(ptr))) {
ret.append(s.charAt(ptr++));
}
return ret.toString();
}
/**
* 基于jdk.stack实现
*
* @param s
* @return
*/
public String decodeString2(String s) {
String res = "";
Stack<Integer> countStack = new Stack<>();//处理数字
Stack<String> resStack = new Stack<>();//处理字符
int idx = 0;
while (idx < s.length()) {
char cur = s.charAt(idx);
//处理数字
if (Character.isDigit(cur)) {
StringBuffer ret = new StringBuffer();
while (Character.isDigit(s.charAt(idx))) {
ret.append(s.charAt(idx++));
}
countStack.push(Integer.parseInt(ret.toString()));
} else if (cur == '[') {//处理"["
resStack.push(res);
res = "";
idx++;
} else if (cur == ']') {//处理"]",处理相匹配的"["之间的字符
StringBuffer temp = new StringBuffer(resStack.pop());
int repeatTimes = countStack.pop();
for (int i = 0; i < repeatTimes; i++) {
temp.append(res);
}
res = temp.toString();
idx++;
} else {//处理普通字符
res += s.charAt(idx++);
}
}
return res;
}
}
41.LeetCode232_用栈实现队列
java
package com.leetcode;
import java.util.Stack;
/**
* LeetCode232:用栈实现队列
*/
public class LeetCode232_MyQueue {
private static Stack<Integer> inStack;//输入栈
private static Stack<Integer> outStack;//输出栈
public LeetCode232_MyQueue() {
inStack = new Stack<>();
outStack = new Stack<>();
}
/**
* 将元素x推到队列的末尾
*
* @param x
*/
public void push(int x) {
inStack.push(x);
}
/**
* 从队列的开头移除并返回元素
*
* @return
*/
public int pop() {
if (outStack.isEmpty()) {
in2out();
}
return outStack.pop();
}
/**
* 返回队列开头的元素
*
* @return
*/
public int peek() {
if (outStack.isEmpty()) {
in2out();
}
return outStack.peek();
}
/**
* 如果队列返回为空,返回true,否则,返回false
*
* @return
*/
public boolean empty() {
return inStack.isEmpty() && outStack.isEmpty();
}
/**
* 从输入栈往输出栈导入元素
*/
private void in2out() {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
}
42.LeetCode876_链表的中间节点_java实现
java
package com.leetcode;
/**
* leetCode876_链表的中间结点
* 解题思路:采用快慢指针
*/
public class LeetCode876 {
public ListNode middleNode(ListNode head) {
ListNode slow=head,fast=head;
while (fast!=null&&fast.next!=null){
slow=slow.next;//慢指针每次移动一个节点
fast=fast.next.next;//快指针每次移动两个节点
}
return slow;
}
}
class ListNode{
int val;
ListNode next;
ListNode(int x){
this.val=x;
next=null;
}
ListNode(int x,ListNode next){
this.val=x;
this.next=next;
}
}
43.LeetCode234_回文链表_java实现
java
package com.leetcode;
/**
* LeetCode234:回文链表
* <p>
* 实现思路:采用双指针,翻转链表的后半部分,然后链表的前半部分与后半部分比较
*/
public class LeetCode234 {
public boolean isPalindrome(ListNode234 head) {
ListNode234 fast = head, slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//如果链表是奇数个结点,把正中的归到左边
if (fast != null) {
slow = slow.next;
}
slow = reverse(slow);
fast = head;//快指针移动到头部
//判断快慢指针是否相遇,相遇则是回文返回true,否则返回false
while (slow != null) {
if (fast.val != slow.val) {
return false;
}
fast = fast.next;
slow = slow.next;
}
return true;
}
/**
* 翻转链表右半部分
*
* @param head
* @return
*/
private ListNode234 reverse(ListNode234 head) {
ListNode234 prev = null;
while (head != null) {
ListNode234 next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
}
}
class ListNode234 {
int val;
ListNode234 next;
ListNode234() {
}
ListNode234(int val) {
this.val = val;
}
ListNode234(int val, ListNode234 next) {
this.val = val;
this.next = next;
}
}
44.LeetCode142_环形链表II_java实现
java
package com.leetcode;
/**
* leetcode142. 环形链表 II:
*
* 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
* 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
* 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
* 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
* 不允许修改 链表。
*
* 解题思路:采用快慢指针,检测是否存在环(检测快慢指针是否相等),则存在环;存在环,则返回开始节点
*/
public class LeetCode142 {
public ListNode142 detectCycle(ListNode142 head){
if(head==null)return null;
ListNode142 slowPtr=head,fastPtr=head;
boolean loopExists=false;
while (fastPtr.next!=null&&fastPtr.next.next!=null){
slowPtr=slowPtr.next;
fastPtr=fastPtr.next.next;
if(slowPtr==fastPtr){
loopExists=true;
break;
}
}
if(loopExists){//环存在
slowPtr=head;
while (slowPtr!=fastPtr){
fastPtr=fastPtr.next;
slowPtr=slowPtr.next;
}
return slowPtr;//返回环的开始节点
}
return null;//环不存在
}
}
class ListNode142 {
int val;
ListNode142 next;
ListNode142(int x) {
val = x;
next = null;
}
}
45. LeetCode160_相交链表_java实现
java
package com.leetcode;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* LeetCode160:相交链表
*/
public class LeetCode160 {
public static ListNode getIntersectionNode(ListNode headA,ListNode headB){
Set<ListNode> visited=new HashSet<>();
ListNode tmp=headA;
while (tmp!=null){
visited.add(tmp);
tmp=tmp.next;
}
tmp=headB;
while (tmp!=null){
if(visited.contains(tmp)){
return tmp;
}
tmp=tmp.next;
}
return null;
}
public static void main(String[] args) {
ListNode n3=new ListNode(8);
ListNode n4=new ListNode(4);
ListNode n5=new ListNode(5);
ListNode headA=new ListNode(4);
ListNode n2=new ListNode(1);
headA.next=n2;
n2.next=n3;
n3.next=n4;
n4.next=n5;
ListNode headB=new ListNode(5);
ListNode b2=new ListNode(6);
ListNode b3=new ListNode(1);
headB.next=b2;
b2.next=b3;
b3.next=n3;
ListNode result= getIntersectionNode(headA,headB);
ListNode tmp=result;
while (tmp!=null){
System.out.println(" result:"+tmp.val);
tmp=tmp.next;
}
}
}
class ListNode{
int val;
ListNode next;
ListNode(int x){
this.val=x;
next=null;
}
}
46. leetcode141环形链表(链表是否有环)java实现
java
package com.leetcode;
import java.util.HashSet;
/**
* LeetCode141:环形链表。
* 解题思路:判断链表是否有环,也就是节点是否被重复访问了
*/
public class LeetCode141ListIsCycle {
/**
* 方法1:hashset检测链表是否有环
* @param head
* @return
*/
public static boolean hasCycle(ListNode1 head) {
HashSet<ListNode1> set=new HashSet<>();
while (head!=null){
if(set.contains(head)){
return true;
}
set.add(head);
head = head.next;
}
return false;
}
/**
* 方法2:采用快慢指针
* @param head
* @return
*/
public static boolean hasCycle2(ListNode1 head) {
HashSet<ListNode1> set=new HashSet<>();
ListNode1 slow=head;
ListNode1 fast=head;
while (fast!=null&&fast.next!=null){
//慢指针走一步
slow=slow.next;
//快指针每次走两步
fast=fast.next.next;
//如果快慢相遇,有环。
if(slow==fast){
return true;
}
}
return false;
}
}
class ListNode1{
int val;
ListNode1 next;
ListNode1(int x){
val=x;
next=null;
}
}
47. leetCode102_二叉树的层序遍历_java实现
java
package com.leetcode;
import java.util.*;
/**
* LeetCode102:二叉树的层序遍历
*/
public class LeetCode102 {
public static List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> levelNodeSet=new ArrayList<>();
if(root==null){
return levelNodeSet;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);///将根节点放入队列中,然后不断遍历队列
while (queue.size()>0){
//获取当前队列的长度即当前这一层的节点个数
int currentLevelSize=queue.size();
//存放当前层的节点元素
List<Integer> levelEle=new ArrayList<>();
for(int i=0;i<currentLevelSize;i++){
TreeNode node = queue.poll();
if(node!=null){
levelEle.add(node.val);
if(node.left!=null){
queue.add(node.left);
}
if(root.right!=null){
queue.add(node.right);
}
}
}
if(levelEle.size()>0){
levelNodeSet.add(levelEle);
}
}
return levelNodeSet;
}
public static void main(String[] args) {
//1.初始化二叉树:首先初始化节点,然后构建引用(指针)
//初始化节点
TreeNode n1=new TreeNode(3);
TreeNode n2=new TreeNode(9);
TreeNode n3=new TreeNode(20);
TreeNode n4=new TreeNode(15);
TreeNode n5=new TreeNode(7);
//构建节点之间的引用(指针)
n1.left=n2;
n1.right=n3;
n3.left=n4;
n3.right=n5;
System.out.println(levelOrder(n1));
}
}
package com.leetcode;
/**
* 定义二叉树节点
*/
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(){}
TreeNode(int val){
this.val=val;
}
TreeNode(int val,TreeNode left,TreeNode right){
this.val=val;
this.left=left;
this.right=right;
}
}
48. LeetCode83_删除排序链表中的重复元素_java实现
java
package com.leetcode;
import com.datastructure.ListNode;
/**
* LeetCode83:删除排序链表中的重复元素
*/
public class LeetCode83 {
/**
* 方法1:遍历链表,直接跳过相同节点,把当前节点指针next指向下下个节点
* @param head
* @return
*/
public static ListNode deleteDuplicates(ListNode head) {
if(head==null){
return head;
}
ListNode currentNode=head;
while (null!=currentNode.next){
if(currentNode.next.val==currentNode.val){
currentNode.next=currentNode.next.next;//跳过相同节点,直接把当前节点指针next的指向下下个节点
}else{
currentNode=currentNode.next;//不同节点,正常指向
}
}
return head;
}
/**
* 方法2:递归处理,本质是将链表压栈后倒序处理
* @param head
* @return
*/
public static ListNode deleteDuplicates2(ListNode head) {
if(head==null||head.next==null)return head;
head.next=deleteDuplicates2(head.next);
return head.val==head.next.val? head.next:head;
}
public static void main(String[] args) {
// int[] head={1,1,2};
// ListNode L1= ListNode.arrToLinkedList(head);
// ListNode resultNode1=deleteDuplicates(L1);
// while (resultNode1!=null){
// System.out.println("resultNode1.val = " + resultNode1.val);
// resultNode1=resultNode1.next;
//
// }
// int[] head={1,1,2,3,3};
// ListNode L1= ListNode.arrToLinkedList(head);
// ListNode resultNode1=deleteDuplicates(L1);
// while (resultNode1!=null){
// System.out.println("resultNode1.val = " + resultNode1.val);
// resultNode1=resultNode1.next;
//
// }
int[] head={1,1,2,3,3};
ListNode L1= ListNode.arrToLinkedList(head);
ListNode resultNode1=deleteDuplicates2(L1);
while (resultNode1!=null){
System.out.println("resultNode1.val = " + resultNode1.val);
resultNode1=resultNode1.next;
}
}
}
49.LeetCode21_合并两个有序链表_java实现
java
package com.leetcode;
import com.datastructure.ListNode;
/**
* LeetCode21MergeSortedLinkedList:合并两个有序链表
*/
public class LeetCode21MergeSortedLinkedList {
/**
* 方法1:使用循环+双指针
* @param list1
* @param list2
* @return
*/
public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1==null)return list2;
if(list2==null)return list1;
//引入结果节点p
ListNode resultNode=new ListNode(0);
ListNode p=resultNode;
//使用循环+双指针
while (list1!=null&&list2!=null){
if(list1.val<list2.val){
p.next=list1;
list1 = list1.next;
}else{
p.next=list2;
list2=list2.next;
}
p=p.next;
}
//追加p尾节点
if(list1!=null){
p.next=list1;
}
if(list2!=null){
p.next=list2;
}
return resultNode.next;
}
/**
* 方法:使用递归合并短链表
* @param list1
* @param list2
* @return
*/
public static ListNode mergeTwoLists2(ListNode list1, ListNode list2) {
if(list1==null)return list2;
if (list2==null)return list1;
if(list1.val<list2.val){
list1.next=mergeTwoLists2(list1.next,list2);
return list1;
}
list2.next=mergeTwoLists2(list1,list2.next);
return list2;
}
public static void main(String[] args) {
int[] l1={1,2,4};
ListNode L1= ListNode.arrToLinkedList(l1);
int[] l2={1,3,4};
ListNode L2= ListNode.arrToLinkedList(l2);
// ListNode resultNode= mergeTwoLists(L1,L2);
// while (resultNode.next!=null){
// System.out.println("resultNode.val = " + resultNode.val);
// resultNode=resultNode.next;
//
// }
ListNode resultNode2= mergeTwoLists2(L1,L2);
while (resultNode2.next!=null){
System.out.println("resultNode2.val = " + resultNode2.val);
resultNode2=resultNode2.next;
}
//
// int[] l1={};
// ListNode L1= ListNode.arrToLinkedList(l1);
//
// int[] l2={};
// ListNode L2= ListNode.arrToLinkedList(l2);
// ListNode resultNode= mergeTwoLists(L1,L2);
// while (resultNode!=null){
// System.out.println("resultNode.val = " + resultNode.val);
// resultNode=resultNode.next;
// }
// int[] l1={};
// ListNode L1= ListNode.arrToLinkedList(l1);
//
// int[] l2={0};
// ListNode L2= ListNode.arrToLinkedList(l2);
// ListNode resultNode= mergeTwoLists(L1,L2);
// while (resultNode!=null){
// System.out.println("resultNode.val = " + resultNode.val);
// resultNode=resultNode.next;
// }
}
}
package com.datastructure;
/**
* 单链表节点类
*
*/
public class ListNode {
public int val;//节点值
public ListNode next;//指向下一个节点的引用
public ListNode(int x){
val=x;
}
public ListNode(){
}
/* Generate a linked list with an array */
public static ListNode arrToLinkedList(int[] arr) {
ListNode dum = new ListNode(0);
ListNode head = dum;
for (int val : arr) {
head.next = new ListNode(val);
head = head.next;
}
return dum.next;
}
/* Get a list node with specific value from a linked list */
public static ListNode getListNode(ListNode head, int val) {
while (head != null && head.val != val) {
head = head.next;
}
return head;
}
}
50.LeetCode448_找出所有数组中消失的数字_java实现
java
package com.leetcode;
import java.util.*;
/**
* LeetCode448FindDisappearedNumInArr:找出所有数组中消失的数字
*/
public class LeetCode448FindDisappearedNumInArr {
/**
* 方法1.hashset,找出没出现的数字
*/
public static List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> result = new ArrayList<>();
if (nums == null || nums.length == 0) {
return result;
}
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int n = nums.length;
for (int i = 1; i <= n; i++) {
if (!set.contains(i)) {
result.add(i);
}
}
return result;
}
/**
*
* @param nums
* @return
*/
public static List<Integer> findDisappearedNumbers2(int[] nums) {
int n=nums.length;
//1.对数组中数字进行遍历
for (int num : nums) {
//对n取模来还原出本来的值
int x=(num-1)%n;
nums[x]+=n;
}
List<Integer> result=new ArrayList<>();
for(int i=0;i<n;i++){
//2.找出数组中缺失的数值
if(nums[i]<=n){
result.add(i+1);
}
}
return result;
}
public static void main(String[] args) {
// int[] nums = {4, 3, 2, 7, 8, 2, 3, 1};
// System.out.println("findDisappearedNumbers(nums) = " + findDisappearedNumbers(nums));
// int[] nums = {1,1};
// System.out.println("findDisappearedNumbers(nums) = " + findDisappearedNumbers(nums));
// int[] nums = {4, 3, 2, 7, 8, 2, 3, 1};
// System.out.println("findDisappearedNumbers2(nums) = " + findDisappearedNumbers2(nums));
int[] nums = {1,1};
System.out.println("findDisappearedNumbers2(nums) = " + findDisappearedNumbers2(nums));
}
}
51.LeetCode88_合并有序数组_java实现
java
package com.leetcode;
import java.util.Arrays;
/**
* LeetCode88_MergeSortedArray:合并有序数组
*
*/
public class LeetCode88_MergeSortedArray {
/*
* 方法1:把nums2的值赋值给num2,然后排序
* @param nums1
* @param m
* @param nums2
* @param n
*/
public static void merge(int[] nums1, int m, int[] nums2, int n) {
for(int i=0;i<n;i++){
nums1[m+i]=nums2[i];
}
Arrays.sort(nums1);
System.out.print("arr={");
for (int i : nums1) {
System.out.print(" " + i+" ");
}
System.out.print("}");
}
/**
* 方法2:指针倒序,两两比较
* @param nums1
* @param m
* @param nums2
* @param n
*/
public static void merge2(int[] nums1, int m, int[] nums2, int n) {
int k=m+n;
for(int index=k-1,nums1Index=m-1,nums2Index=n-1;index>=0;index--){
if(nums1Index<0){//nums1已经取完,完全取nums2的值即可
nums1[index]=nums2[nums2Index];
nums2Index--;
}else if(nums2Index<0){//nums2已经取完,完全取num1的值即可,直接跳出
break;
}else if(nums1[nums1Index]>nums2[nums2Index]){//nums1的元素值大于nums2的值,直接取nums1的值
nums1[index]=nums1[nums1Index];
nums1Index--;
}else{//nums2的元素值大于nums1的值,直接取nums2的值
nums1[index]=nums2[nums2Index];
nums2Index--;
}
}
System.out.print("arr={");
for (int i : nums1) {
System.out.print(" " + i+" ");
}
System.out.print("}");
}
public static void main(String[] args) {
// int[] nums1={1,2,3,0,0,0};
// int[] nums2={2,5,6};
// int m=3,n=3;
// merge(nums1,m,nums2,n);
// int[] nums1={1};
// int[] nums2={};
// int m=1,n=0;
// merge(nums1,m,nums2,n);
//
// int[] nums1={0};
// int[] nums2={1};
// int m=0,n=1;
// merge(nums1,m,nums2,n);
// int[] nums1={1,2,3,0,0,0};
// int[] nums2={2,5,6};
// int m=3,n=3;
// merge2(nums1,m,nums2,n);
// int[] nums1={1};
// int[] nums2={};
// int m=1,n=0;
// merge2(nums1,m,nums2,n);
int[] nums1={0};
int[] nums2={1};
int m=0,n=1;
merge2(nums1,m,nums2,n);
}
}
52. leetcode70_爬楼梯_java多种方法实现
java
package com.leetcode;
import java.util.HashMap;
import java.util.Map;
/**
* leetcode70_爬楼梯
* 假设正在爬楼梯,需要n阶才能到达楼顶。
* 每次可以爬1或2个台阶。你要有多少中不同的方法可以爬到楼顶?
* 注意:给定的n是一个正整数
*/
public class LeetCode70 {
/**
* 递归解法
* @param n
* @return
*/
public static int climStairWithRecursive(int n){
if(n==1)return 1;
if(n==2)return 2;
return climStairWithRecursive(n-1)+climStairWithRecursive(n-2);
}
private static Map<Integer,Integer> storeMap=new HashMap<>();//保存求解过程中间值
/**
* 递归+hashmap解法
* @param n
* @return
*/
public static int climStairWithRecursiveHashMap(int n){
if(n==1)return 1;
if(n==2)return 2;
if(null!=storeMap.get(n)){//从hashmap中获取求解过程中已经存在的中间值
return storeMap.get(n);
}else{
int result=climStairWithRecursiveHashMap(n-1)+climStairWithRecursiveHashMap(n-2);//递归求解
storeMap.put(n,result);//保存计算过程中的中间值
return result;
}
}
/**
* 循环解法,自底向上累加
* @param n
* @return
*/
public static int climStairWithLoopBotton2Up(int n){
if(n==1)return 1;
if(n==2)return 2;
//存储计算结果
int result=0;
//存在中间过程
int pre=2;
int prepre=1;
for(int i=3;i<=n;++i){
result=pre+prepre;
//替换中间过程变量
prepre=pre;
pre=result;
}
return result;
}
public static void main(String[] args) {
// System.out.println("climStairWithRecursive(2) = " + climStairWithRecursive(2));
// System.out.println("climStairWithRecursive(3) = " + climStairWithRecursive(3));
// System.out.println("climStairWithRecursive(45) = " + climStairWithRecursive(45));
// System.out.println("climStairWithRecursiveHashMap(2) = " + climStairWithRecursiveHashMap(2));
// System.out.println("climStairWithRecursiveHashMap(3) = " + climStairWithRecursiveHashMap(3));
// System.out.println("climStairWithRecursiveHashMap(45) = " + climStairWithRecursiveHashMap(45));
System.out.println("climStairWithLoopBotton2Up(2) = " + climStairWithLoopBotton2Up(2));
System.out.println("climStairWithLoopBotton2Up(3) = " + climStairWithLoopBotton2Up(3));
System.out.println("climStairWithLoopBotton2Up(45) = " + climStairWithLoopBotton2Up(45));
}
}
53. leetcode136_只出现一次的数字_java实现
java
package com.leetcode;
/**
* leetcode136:只出现一次的数字
* 解题思路:采用异或运算
* (一个数与它本身做异或运算结果是0,即 a^a=0;
* 一个数与0做异或运算结果为它本身,即a^0=a)
*
* 只出现一次的数字:
* 只要把所有数字进行异或,成对儿的数字就会变成 0,
* 落单的数字和0做异或还是本身,所以最后异或的结果就是只出现一次的元素。
*/
public class leetcode136 {
public static int singleNumber(int[] nums) {
int result=0;
for (int n : nums) {
result^=n;
}
return result;
}
public static void main(String[] args) {
int[] nums={2,2,1};
System.out.println("singleNumber(nums) = " + singleNumber(nums));
int[] nums2={4,1,2,1,2};
System.out.println("singleNumber(nums) = " + singleNumber(nums2));
int[] num3={1};
System.out.println("singleNumber(num3) = " + singleNumber(num3));
}
}
54. LeetCode283_移动零_Java实现
java
package com.leetcode;
import java.util.Arrays;
/**
* LeetCode283:移动零
*/
public class LeetCode283 {
/**
* 双指针
* @param nums
*/
public static void moveZeroes(int[] nums) {
if(nums==null){
return;
}
//1.remove nums中0
int slowIndex=0;
for(int fastindex=0;fastindex<nums.length;fastindex++){
if(nums[fastindex]!=0){
nums[slowIndex]=nums[fastindex];
slowIndex++;
}
}
//2.除0之后的慢指针数组元素补零
for(;slowIndex<nums.length;slowIndex++){
nums[slowIndex]=0;
}
System.out.println("nums[slowIndex]="+ Arrays.toString(nums));
}
public static void moveZeroes2(int[] nums) {
if(nums==null||nums.length==0){
return;
}
int insertIndex=0;
for (int num : nums) {
if(num!=0){
nums[insertIndex]=num;
insertIndex++;
}
}
for (;insertIndex<nums.length;insertIndex++){
nums[insertIndex]=0;
}
System.out.println("nums[insertIndex] = " + Arrays.toString(nums));
}
public static void main(String[] args) {
int[]nums1 = {0,1,0,3,12};
moveZeroes(nums1);
moveZeroes2(nums1);
//
int[]nums2 = {0};
moveZeroes(nums2);
moveZeroes2(nums2);
int[]nums3= {1};
moveZeroes(nums3);
moveZeroes2(nums3);
int[]nums4 = {1,0};
moveZeroes(nums4);
moveZeroes2(nums4);
int[] num5={45192,0,-659,-52359,-99225,-75991,0,-15155,27382,59818,0,-30645,-17025,81209,887,64648};
moveZeroes(num5);
moveZeroes2(num5);
}
}
55. LeeCode347:前k个高频元素_Java实现
java
package com.leetcode;
import java.util.*;
/**
* LeeCode347:前k个高频元素
*/
public class LeeCode347 {
public static int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new TreeMap<>();
for(int i=0;i<nums.length;i++){
int count=map.getOrDefault(nums[i],0);
map.put(nums[i],count+1);
}
LinkedList<Map.Entry<Integer, Integer>> list = new LinkedList<>(map.entrySet());
Comparator<Map.Entry<Integer, Integer>> comparator = Comparator.comparing(Map.Entry::getValue);
Collections.sort(list,comparator);
int index=0;
int[] result=new int[k];
for(int i=list.size();list.size()>0;i--){
if(index>=k) {
break;
}
Map.Entry<Integer, Integer> entry= list.get(i-1);
result[index]=entry.getKey().intValue();
index++;
}
return result;
}
public static void main(String[] args) {
// int[] nums={1,1,1,2,2,3};
// int[] result= topKFrequent(nums, 2);
// for (int i : result) {
// System.out.println("i="+i);
// }
// int[] nums2={1};
// int[] result= topKFrequent(nums2, 1);
// for (int i : result) {
// System.out.println("i="+i);
// }
// int[] nums3={-1,-1};
// int[] result= topKFrequent(nums3, 1);
// for (int i : result) {
// System.out.println("i="+i);
// }
int[] nums4={4,1,-1,2,-1,2,3};
int[] result= topKFrequent(nums4, 2);
for (int i : result) {
System.out.println("i="+i);
}
}
}
56. LeeCode215_数组中的第K个最大元素_java实现
java
package com.leetcode;
import java.util.Collections;
import java.util.PriorityQueue;
/**
* LeeCode215
* 数组中的第K个最大元素
*/
public class LeeCode215 {
public static int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> maxHeap=new PriorityQueue<>(Collections.reverseOrder());
for(int num:nums){
maxHeap.add(num);
}
int result;
for(int i=1;i<k;i++){
maxHeap.poll();
}
return maxHeap.peek();
}
public static void main(String[] args) {
// int[]nums1={3,2,1,5,6,4};
int[] num2={3,2,3,1,2,4,5,5,6};
// int[] num3={2,1};
// System.out.println(findKthLargest(nums1,2));
System.out.println(findKthLargest(num2,4));
// System.out.println(findKthLargest(num3,2));
}
}
57. LeetCode9_回文数_Java实现
java
package com.leetcode;
/**
* LeetCode9:回文数
* 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
*
* 回文数 是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
*
* 例如,121 是回文,而 123 不是。
*/
public class LeetCode9 {
public static boolean isPalindrome(int x) {
String str=String.valueOf(x);
char[] chars= str.toCharArray();
char[] charsNew=new char[chars.length];
int index=0;
for(int i=chars.length-1;i>=0;i--){
charsNew[index]=chars[i];
index++;
}
System.out.println("charsNew:"+new String(charsNew));
if(str.equals(new String(charsNew))){
return true;
}else {
return false;
}
}
public static boolean isPalindrome2(int x) {
boolean result=true;
String inputStr=String.valueOf(x);
int length=inputStr.length();
for(int i=0;i<length/2;i++){
if(inputStr.charAt(i)!=inputStr.charAt(length-i-1)){
result=false;
break;
}
}
return result;
}
public static void main(String[] args) {
System.out.println("isPalindrome(121) = " + isPalindrome(121));
System.out.println("isPalindrome(-121) = " + isPalindrome(-121));
System.out.println("isPalindrome(10) = " + isPalindrome(10));
System.out.println("isPalindrome2(123) = " + isPalindrome2(123));
System.out.println("isPalindrome2(212) = " + isPalindrome2(212));
}
}
58.leetcode704_二分查找实现
java
package com.leetcode;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Leecode704 {
public static int search(int[]nums,int target){
//初始化左闭右闭区间[left,right]
int left=0,right=nums.length-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left = mid+1; // target 在右区间,所以[middle + 1, right]
}else if(nums[mid]>target){
right=mid-1; // target 在左区间,所以[left, middle - 1]
}else{
return mid; // 数组中找到目标值,直接返回下标
}
}
return -1;
}
public static void main(String[] args) {
int[] nums={-1,0,3,5,9,12};
System.out.println(search(nums,12));
}
}
59. LeetCode151_反转字符串中的单词java实现
java
package com.leetcode;
import java.sql.Statement;
import java.util.Stack;
/**
* LeetCode151:反转字符串中的单词
*/
public class LeetCode151_ReverseWord {
public static String reverseWords(String s){
String[] words= s.split(" ");
Stack<String> stack = new Stack<>();
for(String word:words){
if(!word.equals("")){
stack.push(word.trim());
}
}
StringBuffer stringBuffer = new StringBuffer();
while (stack.size()>0){
stringBuffer.append(stack.pop()).append(" ");
}
return stringBuffer.toString().trim();
}
public static void main(String[] args) {
String str1="the sky is blue";
String str2 = " hello world ";
String str3="a good example";
System.out.println("reverseStr1:"+reverseWords(str1));
System.out.println("reverseStr2:"+reverseWords(str2));
System.out.println("reverseStr3:"+reverseWords(str3));
}
}
60.leetcode_078. 合并K个升序链表.小顶堆实现
java
/**
* 构造单链表节点
*/
class ListNode{
int value;//节点值
ListNode next;//指向后继节点的引用
public ListNode(){}
public ListNode(int value){
this.value=value;
}
public ListNode(int value,ListNode next){
this.value=value;
this.next=next;
}
}
package com.ag;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
/**
* leetcode_078. 合并K个升序链表
* 解题思路:
* 1.定义小根堆的大小为K,然后从每个链表拿一个元素进来构造最小堆
* 2.取走堆顶元素(一定是最小值)插入到新链表的表尾,然后将该元素所在的链表再拿一个元素进来,重新构造小顶堆
*
*/
public class MergeKASCList {
public ListNode mergeKLists(List<ListNode> lists){
//1.判断边界
if(lists==null||lists.size()==0){
return null;
}
//2.构造最小堆
Queue<ListNode> minHeap=new PriorityQueue<>((o1, o2) -> o1.value-o2.value);
for (ListNode listNode : lists) {
if(listNode!=null){
minHeap.offer(listNode);//元素入堆
}
}
//3.构造合并后的新链表
ListNode head=new ListNode(0);
ListNode tail=head;
while (!minHeap.isEmpty()){
//堆顶元素出堆,获取链表最小节点,加入新链表队尾
tail.next=minHeap.poll();
tail=tail.next;
if(tail.next!=null){
minHeap.offer(tail.next);//最小链表节点的下一个节点加入最小堆 (重新构造小顶堆)
}
}
return head.next;
}
public static void main(String[] args) {
List<ListNode> lists=new ArrayList<>();
//1.初始化各个节点
ListNode node1=new ListNode(1);
ListNode node2=new ListNode(4);
ListNode node3=new ListNode(5);
ListNode node4=new ListNode(1);
ListNode node5=new ListNode(3);
ListNode node6=new ListNode(4);
ListNode node7=new ListNode(2);
ListNode node8=new ListNode(6);
//2.构建节点之间的引用
node1.next=node2;
node2.next=node3;
node4.next=node5;
node5.next=node6;
node7.next=node8;
//打印链表
// printLinkedList(node1);
// printLinkedList(node4);
// printLinkedList(node7);
//3.将链表头节点添加到list
lists.add(node1);
lists.add(node4);
lists.add(node7);
//4.合并链表
MergeKASCList mergeKASCList=new MergeKASCList();
ListNode listNode=mergeKASCList.mergeKLists(lists);
//5.打印合并后的链表
printLinkedList(listNode);
}
/**
* 打印链表
* @param head
*/
public static void printLinkedList(ListNode head) {
List<String> list = new ArrayList<>();
while (head != null) {
list.add(String.valueOf(head.value));
head = head.next;
}
System.out.println(String.join(" -> ", list));
}
}

61. leetcode_7:整数反转
java
package com.ag;
/**
* leetcode_7. 整数反转
*
*/
public class ReverseInt {
public static void main(String[] args) {
System.out.println(1/2);
System.out.println(reverse(123123));
}
public static int reverse(int x){
long n=0;
while(x!=0){
n=n*10+x%10;
System.out.print("x%10取模:"+x%10+",n:"+n);
x=x/10;
System.out.println("; x/10除于:"+x);
}
return (int)n==n?(int)n:0;
}
}