1、两数之和
public int[] twoSum(int[] nums, int target) {
int [] result=new int[2];
HashMap map=new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
if(!map.containsKey(target-nums[i])){
map.put(nums[i],i);
}else{
result[0]=(int)map.get(target-nums[i]);
result[1]=i;
}
}
return result;
}
containsKey
2、 字母异位词分组
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> result = new ArrayList<>();
HashMap<String, List<String>> map = new HashMap<>();
for (int i = 0; i < strs.length; i++) {
char[] chars = strs[i].toCharArray();
Arrays.sort(chars);
String key = new String(chars);
if (!map.containsKey(key)) {
List<String> list = new ArrayList();
list.add(strs[i]);
map.put(key, list);
} else {
List<String> addList = map.get(key);
addList.add(strs[i]);
}
}
for (Object o : map.keySet()) {
result.add(map.get(o));
}
return result;
}
new String(); 创建list集合、map集合等
3、最长连续序列
HashSet<Integer> set = new HashSet<>();
int res = 0;
for (int num : nums) {
set.add(num);
}
for (int i = 0; i < nums.length; i++) {
if (!set.contains(nums[i] - 1)) {
int curNum = nums[i];
int curLen = 1;
while (set.contains(curNum + 1)) {
curNum = curNum + 1;
curLen = curLen + 1;
}
res = Math.max(res, curLen);
}
}
return res;
4、移动零
public void moveZeroes(int[] nums) {
int left = 0;
if (nums.length == 0 || nums.length == 1) return;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
int temp = nums[i];
nums[i] = nums[left];
nums[left] = temp;
left++;
}
}
}
5、盛最多少的容器
public int maxArea(int[] height) {
int left=0;
int right=height.length-1;
int vol=0;
int result=0;
while(left<right){
if(height[left]>height[right]){
vol=(right-left)*height[right];
right--;
}else{
vol=(right-left)*height[left];
left++;
}
result=result>vol?result:vol;
}
return result;
}
6、三数之和
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(nums);
if(nums.length<3){
return res;
}
for(int i=0;i<nums.length-2;i++){
if (i > 0 && nums[i] == nums[i - 1]) {
continue; // 跳过重复元素
}
int left=i+1;
int right=nums.length-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]==0){
List<Integer> midList=new ArrayList<>();
midList.add(nums[i]);
midList.add(nums[left]);
midList.add(nums[right]);
res.add(midList);
while (left < right && nums[left] == nums[left + 1]) {
left++; // 跳过重复元素
}
while (left < right && nums[right] == nums[right - 1]) {
right--; // 跳过重复元素
}
right--;
left++;
}else if(nums[i]+nums[left]+nums[right]>0){
right--;
}else{
left++;
}
}
}
return res;
}
7、除自身以外数组的乘积
public int[] productExceptSelf(int[] nums) {
int n=nums.length;
int[] res=new int[n];
int[] right=new int[n];
right[n-1]=1;
int[] left=new int[n];
left[0]=1;
for(int i=1;i<n;i++){
left[i]=left[i-1]*nums[i-1];
}
for(int i=n-2;i>=0;i--){
right[i]=right[i+1]*nums[i+1];
}
for(int i=0;i<n;i++){
res[i]=left[i]*right[i];
}
return res;
}
8、轮转数组
public void rotate(int[] nums, int k) {
if(k==nums.length) return;
resverse(nums,0,nums.length-1);
resverse(nums,0,(k-1)%nums.length);
resverse(nums,(k)%nums.length,nums.length-1);
}
public void resverse(int[] nums,int begin,int end){
while(begin<end){
int temp=nums[end];
nums[end]=nums[begin];
nums[begin]=temp;
begin++;
end--;
}
}
9、合并区间
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals,(int[] o1,int[] o2)->o1[0]-o2[0]);
LinkedList<int []> list=new LinkedList<>();
list.add(intervals[0]);
for(int i=1;i<intervals.length;i++){
int[] last=list.getLast();
if(intervals[i][0]<=last[1]){
last[1]=Math.max(intervals[i][1],last[1]);
}else{
list.add(intervals[i]);
}
}
return list.toArray(new int[0][0]);
}
10、最大子数组和
public int maxSubArray(int[] nums) {
int res=0;
int[] maxSum =new int[nums.length];
maxSum[0]=nums[0];
for(int i=1;i<nums.length;i++){
if(maxSum[i-1]>0){
maxSum[i]=maxSum[i-1]+nums[i];
}else{
maxSum[i]=nums[i];
}
}
Arrays.sort(maxSum);
return maxSum[nums.length-1];
}
11、矩阵置零
public void setZeroes(int[][] matrix) {
boolean[] row=new boolean[matrix.length];
boolean[] col=new boolean[matrix[0].length];
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
if(matrix[i][j]==0){
row[i]=true;
col[j]=true;
}
}
}
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
if(row[i]||col[j]){
matrix[i][j]=0;
}
}
}
}
12、螺旋矩阵
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list=new ArrayList<>();
int row=matrix.length;
int col=matrix[0].length;
int left=0;
int right=col-1;
int up=0;
int down=row-1;
while(list.size()<row*col){
if(up<=down){
for(int j=left;j<=right;j++){
list.add(matrix[up][j]);
}
up++;
}
if(left<=right){
for(int j=up;j<=down;j++){
list.add(matrix[j][right]);
}
right--;
}
if(up<=down){
for(int j=right;j>=left;j--){
list.add(matrix[down][j]);
}
down--;
}
if(left<=right){
for(int j=down;j>=up;j--){
list.add(matrix[j][left]);
}
left++;
}
}
return list;
}
13、旋转图像
class Solution {
public void rotate(int[][] matrix) {
int m=matrix.length;
for(int i=0;i<m;i++){
for(int j=i;j<m;j++){
int temp=matrix[i][j];
matrix[i][j]=matrix[j][i];
matrix[j][i]=temp;
}
}
for(int i=0;i<m;i++){
reserve(matrix[i],0,matrix[0].length-1);
}
}
public void reserve(int[] nums,int begin,int end){
while(begin<end){
int temp=nums[begin];
nums[begin]=nums[end];
nums[end]=temp;
begin++;
end--;
}
}
}
14、搜索二维矩阵
public boolean searchMatrix(int[][] matrix, int target) {
boolean res=false;
int m=matrix.length;
int n=matrix[0].length;
for(int i=0;i<m;i++){
for(int j=0;j<n;){
if(target==matrix[i][j]){
res=true;
return res;
}
if(target<matrix[i][j]){
break;
}
if(target>matrix[i][j]){
j++;
}
}
}
return res;
}
15、无重复字符的最长字串
public int lengthOfLongestSubstring(String s) {
int left = 0;
int right = 0;
int res = 0;
HashMap<Character, Integer> map = new HashMap<>();
while (right < s.length()) {
char c = s.charAt(right);
right++;
map.put(c, map.getOrDefault(c, 0) + 1);
while (map.get(c) > 1) {
char m = s.charAt(left);
left++;
map.put(m, map.get(m) - 1);
}
res = Math.max(res, right - left);
}
return res;
}
16、找到字符串中的所有字母异位词
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list=new ArrayList<>();
int left=0;
int right=0;
int vaild=0;
HashMap <Character,Integer> p_map=new HashMap<>();
HashMap <Character,Integer> s_map=new HashMap<>();
for(int i=0;i<p.length();i++){
p_map.put(p.charAt(i),p_map.getOrDefault(p.charAt(i),0)+1);
}
while(right<s.length()){
char c=s.charAt(right);
right++;
if(p_map.containsKey(c)){
s_map.put(c,s_map.getOrDefault(c,0)+1);
if(s_map.get(c).equals(p_map.get(c))){
vaild++;
}
}
while(right-left>=p.length()){
if(vaild==p_map.size())
list.add(left);
char m=s.charAt(left);
left++;
if(p_map.containsKey(m)){
if(s_map.get(m).equals(p_map.get(m))){
vaild--;
}
s_map.put(m,s_map.get(m)-1);
}
}
}
return list;
}
17、和为K的子数组
public int subarraySum(int[] nums, int k) {
int res = 0;
int sum = 0;
HashMap<Integer, Integer> sumMap = new HashMap<>();
sumMap.put(0, 1);
for (int num : nums) {
sum += num;
if (sumMap.containsKey(sum - k)) {//sum-k代表从不同起点到当前点的子数组和为k的不同情况
res += sumMap.get(sum - k);
}
sumMap.put(sum, sumMap.getOrDefault(sum, 0) + 1);
}
return res;
}
18、最小覆盖子串
public String minWindow(String s, String t) {
int left=0;
int right=0;
int valid=0;
HashMap<Character, Integer> t_map=new HashMap<>();
HashMap<Character, Integer> s_map=new HashMap<>();
for(int i=0;i<t.length();i++) {
t_map.put(t.charAt(i),t_map.getOrDefault(t.charAt(i),0)+1);
}
int start=0;
int len=Integer.MAX_VALUE;
while(right<s.length()){
char c=s.charAt(right);
if(t_map.containsKey(c)){
s_map.put(c,s_map.getOrDefault(c,0)+1);
if(s_map.get(c).equals(t_map.get(c))) {
valid++;
}
}
right++;
while(valid==t_map.size()){
if(right-left<len){
start=left;
len=right-left;
}
char m=s.charAt(left);
if(t_map.containsKey(m)){
if(s_map.get(m).equals(t_map.get(m))) {
valid--;
}
s_map.put(m,s_map.get(m)-1);
}
left++;
}
}
return len==Integer.MAX_VALUE?"":s.substring(start,start+len);
}
19、相交链表
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode s1=headA;
ListNode s2=headB;
Set<ListNode> set=new HashSet<>();
while(s1!=null){
set.add(s1);
s1=s1.next;
}
while(s2!=null){
if(set.contains(s2)){
return s2;
}
s2=s2.next;
}
return null;
}
20、反转链表
public ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode cur=head;
while(cur!=null){
ListNode temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
21、回文链表
public boolean isPalindrome(ListNode head) {
ListNode cur=head;
List<Integer> list=new ArrayList<>();
while(cur!=null){
list.add(cur.val);
cur=cur.next;
}
int left=0;
int right=list.size()-1;
while(left<right){
if(list.get(left)!=list.get(right)){
return false;
}
left++;
right--;
}
return true;
}
22、环形链表
public boolean hasCycle(ListNode head) {
Set<ListNode> set=new HashSet<>();
ListNode cur=head;
while(cur!=null){
if(set.contains(cur)){
return true;
}else{
set.add(cur);
}
cur=cur.next;
}
return false;
}
23、环形链表2
public ListNode detectCycle(ListNode head) {
Set<ListNode> set=new HashSet<>();
ListNode cur=head;
while(cur!=null){
if(set.contains(cur)){
return cur;
}else{
set.add(cur);
}
cur=cur.next;
}
return null;
}
24、合并两个有序链表
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode head1=list1;
ListNode head2=list2;
ListNode newHead=new ListNode();
ListNode result=newHead;
while(head1!=null && head2!=null){
if(head1.val<=head2.val){
newHead.next=head1;
head1=head1.next;
newHead=newHead.next;
}else{
newHead.next=head2;
head2=head2.next;
newHead=newHead.next;
}
}
if(head1==null){
newHead.next=head2;
}else if(head2==null){
newHead.next=head1;
}
return result.next;
}
25、两数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1=l1;
ListNode head2=l2;
ListNode newHead=new ListNode();
ListNode cur=newHead;
int forward=0;
int curVal=0;
while(head1!=null || head2!=null){
int x=head1==null?0:head1.val;
int y=head2==null?0:head2.val;
int sum=x+y+forward;
forward=sum/10;
curVal=sum%10;
cur.next=new ListNode(curVal);
cur=cur.next;
if(head1!=null){
head1=head1.next;
}
if(head2!=null){
head2=head2.next;
}
}
if(forward!=0){
cur.next=new ListNode(forward);
}
return newHead.next;
}
26、删除链表的倒数第N个结点
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode pre=new ListNode();
pre.next=head;
ListNode fast=pre;
ListNode slow=pre;
for(int i=0;i<=n;i++){
fast=fast.next;
} //快指针先走n+1步
while(fast!=null){
fast=fast.next;
slow=slow.next;
}//快慢指针同时走,直到快指针走到null
slow.next=slow.next.next;
return pre.next;
}
27、两两交换链表中的节点
public ListNode swapPairs(ListNode head) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode pre=dummy;
ListNode cur=head;
while(cur!=null&&cur.next!=null){
ListNode temp=cur.next;
ListNode temp2=cur.next.next;
pre.next=temp;
temp.next=cur;
cur.next=temp2;
pre=cur;
cur=temp2;
}
return dummy.next;
}
28、随机链表的复制
public Node copyRandomList(Node head) {
if(head==null){
return null;
}
//创建一个哈希表,key是原节点,value是新节点
Map<Node,Node> map=new HashMap<>();
Node cur=head;
//将原节点和新节点放入哈希表中
while(cur!=null){
Node newNode=new Node(cur.val);
map.put(cur,newNode);
cur=cur.next;
}
cur=head;
//遍历原链表,设置新节点的next和random
while(cur!=null){
Node newNode=map.get(cur);
if(cur.next!=null){
newNode.next=map.get(cur.next);
}
if(cur.random!=null){
newNode.random=map.get(cur.random);
}
cur=cur.next;
}
return map.get(head);
}
29、排序链表
public ListNode sortList(ListNode head) {
if(head==null || head.next==null){
return head;
}
//找到分割点
ListNode fast=head.next;
ListNode slow=head;
while(fast!=null && fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
ListNode cut=slow.next;
slow.next=null;//断开链表 这步得加上 不然会栈溢出
//递归
ListNode left= sortList(head);
ListNode right=sortList(cut);
//合并
return mergeTwoLists(left,right);
}
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode head1=list1;
ListNode head2=list2;
ListNode newHead=new ListNode();
ListNode result=newHead;
while(head1!=null && head2!=null){
if(head1.val<=head2.val){
newHead.next=head1;
head1=head1.next;
newHead=newHead.next;
}else{
newHead.next=head2;
head2=head2.next;
newHead=newHead.next;
}
}
if(head1==null){
newHead.next=head2;
}else if(head2==null){
newHead.next=head1;
}
return result.next;
}
30、二叉树的中序排列
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res=new ArrayList<>();
inorder(root,res);
return res;
}
public void inorder (TreeNode root,List<Integer> res){
if(root==null){
return;
}
inorder(root.left,res);
res.add(root.val);
inorder(root.right,res);
}
}
31、二叉树的最大深度
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
int left=maxDepth(root.left);
int right=maxDepth(root.right);
return Math.max(left,right)+1;
}
32、翻转二叉树
public TreeNode invertTree(TreeNode root) {
//将以root为根节点的二叉树进行翻转 并且返回翻转之后的根节点
if(root==null){
return null;
}
TreeNode node1=invertTree(root.left);
TreeNode node2=invertTree(root.right);
root.left=node2;
root.right=node1;
return root;
}
33、对称二叉树
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
boolean flag=symmetric(root.left,root.right);
return flag;
}
public boolean symmetric(TreeNode root1,TreeNode root2) {
//判断root节点的左右子树是不是对称的 并且返回判断结果
if(root1==null&&root2==null) return true;
if(root1==null||root2==null) return false;
boolean flag1=symmetric(root1.left,root2.right);
boolean flag2=symmetric(root1.right,root2.left);
return root1.val==root2.val&&flag1&&flag2;
}
34、二叉树的直径
class Solution {
//每一条二叉树的「直径」长度,就是一个节点的左右子树的最大深度之和。
int maxDiameter=0;
public int diameterOfBinaryTree(TreeNode root) {
maxDepth(root);
return maxDiameter;
}
int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftMax = maxDepth(root.left);
int rightMax = maxDepth(root.right);
maxDiameter = Math.max(maxDiameter,leftMax + rightMax);
return 1 + Math.max(leftMax, rightMax);
}
}
35、二叉树的层序遍历
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
if(root==null){ return res;}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
List<Integer> list=new ArrayList<>();
for(int i=0;i<size;i++){
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
res.add(list);
}
return res;
}
36、将有序数组转换为二叉搜索树
public TreeNode sortedArrayToBST(int[] nums) {
TreeNode root=traversal(nums,0,nums.length-1);
return root;
}
public TreeNode traversal(int[] nums,int left,int right) {
//将数组从开始到结尾转换成二叉树 并且返回根节点
if(left>right){
return null;
}
int mid=(left+right)/2;
TreeNode root=new TreeNode(nums[mid]);
root.left=traversal( nums,left,mid-1);
root.right=traversal(nums,mid+1,right);
return root;
}
37、验证二叉搜索树
public boolean isValidBST(TreeNode node) {
return isBst(node, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isBst(TreeNode node, long lower, long upper) {
//根节点是root的二叉树是不是搜索树
if (node == null) {
return true;
}
if (node.val <= lower || node.val >= upper) {
return false;
}
return isBst(node.left, lower, node.val) && isBst(node.right, node.val, upper);
}
38、二叉搜索树中第K小的元素
class Solution {
public int kthSmallest(TreeNode root, int k) {
return inorderTraversal(root).get(k-1);
}
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res=new ArrayList<>();
inorder(root,res);
return res;
}
public void inorder (TreeNode root,List<Integer> res){
if(root==null){
return;
}
inorder(root.left,res);
res.add(root.val);
inorder(root.right,res);
}
}
39、二叉树的右视图
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res=new ArrayList<Integer>();
if(root==null){ return res;}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode node=queue.poll();
if (i == size - 1) {
res.add(node.val);
}
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
}
return res;
}
40、二叉树展开为链表
public void flatten(TreeNode root) {
if(root==null){
return;
}
flatten(root.left);
flatten(root.right);
TreeNode left=root.left;
TreeNode right=root.right;
//将左子树作为右子树
root.left=null;
root.right=left;
//将原先的右子树接到当前右子树的末端
TreeNode p=root;
while(p.right!=null){
p=p.right;
}
p.right=right;
}
41、从前序与中序遍历序列构造二叉树
public TreeNode buildTree(int[] preorder, int[] inorder) {
return build(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
public TreeNode build(int[] preorder,int prestart,int preend,int[]inorder,int instart,int inend){
//build函数是找到以前序中序排列的根节点
if(prestart>preend) return null;
int rootval=preorder[prestart];
TreeNode root=new TreeNode(rootval);
int index=0;
for(int i=instart;i<=inend;i++){
if(inorder[i]==rootval){
index=i;
break;
}
}
int leftsize=index-instart;
root.left=build(preorder,prestart+1,prestart+leftsize,inorder,instart,index-1);
root.right=build(preorder,prestart+leftsize+1,preend,inorder,index+1,inend);
return root;
}
42、路径总和
public int pathSum(TreeNode root, int targetSum) {
if(root==null) return 0;
int num=rootSum(root,targetSum);
num+=pathSum(root.left,targetSum);
num+=pathSum(root.right,targetSum);
return num;
}
public int rootSum(TreeNode root,long targetSum){
int num=0;
if(root==null){return 0;}
long val=root.val;
if(val==targetSum) num++;
num+=rootSum(root.left,targetSum-val);
num+=rootSum(root.right,targetSum-val);
return num;
}
43、二叉树的最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null||root==p||root==q){return root;}
TreeNode left=lowestCommonAncestor(root.left,p,q);
TreeNode right=lowestCommonAncestor(root.right,p,q);
if(left==null) return right;
if(right==null) return left;
return root;
}
44、有效的括号
public boolean isValid(String s) {
Stack<Character> stack=new Stack();
HashMap<Character,Character> map=new HashMap<>();
map.put('(',')');
map.put('{','}');
map.put('[',']');
map.put('?','?');
stack.push('?');
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(map.containsKey(c)){
//注意是containsKey
stack.push(c);
}else if(map.get(stack.pop())!=c){
//调用了stack.pop()元素就已经弹出了
return false;
}
}
return stack.size()==1;
}
45、字符串解码
public String decodeString(String s) {
Stack<Integer> stackMulti=new Stack();
Stack<String> stackRes=new Stack();//存放中间结果的
StringBuilder sb=new StringBuilder();
int multi=0;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(c>='0'&&c<='9'){
multi=multi*10+Integer.parseInt(c+"");
}else if(c=='['){
stackMulti.push(multi);//为括号内字符解码做乘积的准备
stackRes.push(sb.toString());//把之前的结果进行存放
multi=0;
sb=new StringBuilder();//存放括号内的字符
}else if(c==']'){
StringBuilder temp=new StringBuilder();
int curMulti=stackMulti.pop();
for(int j=0;j<curMulti;j++){
temp.append(sb);
}
sb=new StringBuilder(stackRes.pop()+temp);
}else{
sb.append(c);
}
}
return sb.toString();
}
46、每日温度
public int[] dailyTemperatures(int[] temperatures) {
int[] res=new int[temperatures.length];
Stack<Integer> stack=new Stack();
for(int i=0;i<temperatures.length;i++){
int c=temperatures[i];
while(!stack.isEmpty()&&temperatures[stack.peek()]<c){
int j=stack.pop();
res[j]=i-j;
}
stack.push(i);
}
return res;
}
47、数组中的第K个最大元素
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> queue=new PriorityQueue();
for(int num:nums){
queue.offer(num);
if(queue.size()>k){
queue.poll();
}
}
return queue.peek();
}
48、前K个高频元素
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer,Integer> map=new HashMap<>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
PriorityQueue<Integer> queue=new PriorityQueue<>(
(Integer a,Integer b)->map.get(a)-map.get(b));
//按照map的值即出现的次数构造的小顶堆
for(Integer key:map.keySet()){
queue.offer(key);
if(queue.size()>k){
queue.poll();
}
}
int [] res=new int[k];
for(int i=0;i<k;i++){
res[i]=queue.peek();
queue.poll();
}
return res;
}
动态规划
49、爬楼梯
public int climbStairs(int n) {
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
50、杨辉三角
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> res=new ArrayList<>();
for(int i=0;i<numRows;i++){
List<Integer> row=new ArrayList<>();
for(int j=0;j<=i;j++){
if(j==0||j==i){
row.add(1);
}else{
row.add(res.get(i-1).get(j-1)+res.get(i-1).get(j));
}
}
res.add(row);
}
return res;
}//没懂的弄个双重循环
51、打家劫舍
public int rob(int[] nums) {
int [] dp=new int[nums.length+1];
dp[0]=0;
dp[1]=nums[0];
for(int i=2;i<dp.length;i++ ){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[nums.length];
}
52、完全平方数
public int numSquares(int n) {
int [] dp=new int[n+1];
Arrays.fill(dp,n);
dp[0]=0;
dp[1]=1;
for(int i=2;i<n+1;i++){
for(int j=1;j * j <= i; j++){
dp[i]=Math.min(dp[i-j*j]+1,dp[i]);
}
}
return dp[n];
}
53、零钱兑换
public int coinChange(int[] coins, int amount) {
int[] dp=new int[amount+1];
Arrays.fill(dp,amount+1);//这里为什么填充的是amount+1呢
dp[0]=0;
for(int i=1;i<dp.length;i++){
for(int j=0;j<coins.length;j++){
if(i-coins[j]<0){
continue;
}else{
dp[i]=Math.min(dp[i-coins[j]]+1,dp[i]);
}
}
}
return dp[amount]>amount?-1:dp[amount];
}
54、单词拆分
public boolean wordBreak(String s, List<String> wordDict) {
boolean [] dp=new boolean[s.length()+1];
dp[0]=true;
Set<String> set=new HashSet<>();
for(int i=0;i<wordDict.size();i++){
set.add(wordDict.get(i));
}
for(int i=1;i<s.length()+1;i++){
for(int j=0;j<i;j++){
if(dp[j]&&set.contains(s.substring(j,i))){
dp[i]=true;
break;
}
}
}
return dp[s.length()];
}
55、最长递增子序列
public int lengthOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int maxans = 1;
for (int i = 1; i < nums.length; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
maxans = Math.max(maxans, dp[i]);
}
return maxans;
//最大值不一定是出现在最后的
}
56、乘积最大子数组
public int maxProduct(int[] nums) {
int max=Integer.MIN_VALUE;
int imax=1;
int imin=1;
for(int i=0;i<nums.length;i++){
if(nums[i]<0){
int temp=imax;
imax=imin;
imin=temp;
}
imax=Math.max(imax*nums[i],nums[i]);
imin=Math.min(imin*nums[i],nums[i]);
max=Math.max(max,imax);
}
return max;
}
57、分割等和子集
public boolean canPartition(int[] nums) {
int sum=0;
for(int i:nums){
sum+=i;
}
int target=sum/2;
if(sum%2!=0){
return false;
}
int []dp=new int[target+1];
for(int i=0;i<nums.length;i++){
for(int j=target;j>=nums[i];j--){
//背包容量是target,放入的不能比容量大;并且每个元素不能重复放入,所以要从大到小遍历
dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
}
if(dp[target]==target){
return true;
}
}
return dp[target]==target;
}
58、不同路径
public int uniquePaths(int m, int n) {
int [][] dp=new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0||j==0){
dp[i][j]=1;
}else{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
}
return dp[m-1][n-1];
}
59、最小路径和
public int minPathSum(int[][] grid) {
int m=grid.length;
int n=grid[0].length;
int [][] dp=new int [m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0&&j==0){
dp[i][j]=grid[i][j];
}else if(i==0){
dp[i][j]=dp[i][j-1]+grid[i][j];
}else if(j==0){
dp[i][j]=dp[i-1][j]+grid[i][j];
}else{
dp[i][j]=Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
}
return dp[m-1][n-1];
}
60、最长回文子串
public String longestPalindrome(String s) {
if(s==null||s.length()<2){
return s;
}
int len=s.length();
int maxStart=0;
int maxEnd=0;
int maxLen=1;
boolean[][]dp=new boolean[len][len];
for(int i=1;i<len;i++){
for(int j=0;j<i;j++){
if(s.charAt(j)==s.charAt(i)&&(i-j<=2||dp[j+1][i-1])){
//重点是转移方程
dp[j][i]=true;
if(i-j+1>maxLen){
maxLen=i-j+1;
maxStart=j;
maxEnd=i;
}
}
}
}
return s.substring(maxStart,maxEnd+1);
}
61、最长公共子序列
public int longestCommonSubsequence(String text1, String text2) {
int m=text1.length();
int n=text2.length();
int [][] dp=new int[m+1][n+1];
//dp[i][j] 表示 text1[0:i-1] 和 text2[0:j-1] 的最长公共子序列的长度
//text1[0:i-1] 表示的是 text1 的 第 0 个元素到第 i - 1 个元素,两端都包含
for(int i=1;i<m+1;i++){
for(int j=1;j<n+1;j++){
if(text1.charAt(i-1)==text2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m][n];
}
二分查找
62、搜索插入位置
public int searchInsert(int[] nums, int target) {
int left=0;
int right=nums.length-1;
//注意是<=
while(left<=right){
int middle=(left+right)/2;
if(nums[middle]<target){
left=middle+1;
}else if(nums[middle]>target){
right=middle-1;
}else{
return middle;
}
}
return left;
}
63、搜索二维矩阵
public boolean searchMatrix(int[][] matrix, int target) {
int m=matrix.length;
int n=matrix[0].length;
int left=0;
int right=m*n-1;
while(left<=right){
int mid=(left+right)/2;
if(matrix[mid/n][mid%n]<target){
//坐标做一个映射就可以了
left=mid+1;
}else if(matrix[mid/n][mid%n]>target){
right=mid-1;
}else{
return true;
}
}
return false;
}
64、 在排序数组中查找元素的第一个和最后一个位置
public int[] searchRange(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while(left<=right){
int mid=(left+right)/2;
if(target==nums[mid]){
while(target!=nums[left]) left++;//继续循环找就好
while(target!=nums[right]) right--;
return new int[]{left,right};
}else if(target>nums[mid]){
left=mid+1;
}else {
right=mid-1;
}
}
return new int[]{-1,-1};
}
65、搜索旋转排序数组
66、寻找旋转排序数组中的最小值
贪心算法
67、买卖股票的最佳时机
public int maxProfit(int[] prices) {
int min=Integer.MAX_VALUE;
int max=0;
for(int i=0;i<prices.length;i++){
if(prices[i]<min){
min=prices[i];
}else if(prices[i]-min>max){
max=prices[i]-min;
}//中心思想就是在这一天要么买入要么卖出
}
return max;
}
68、跳跃格子
public boolean canJump(int[] nums) {
int n=nums.length;
int maxReach=0;
for(int i=0;i<n;i++){
if(i<=maxReach){//这个点是在最大可达范围之内的话,才会去更新
maxReach=Math.max(maxReach,i+nums[i]);
if(maxReach>=n-1){
return true;
}
}
}
return false;
}
69、跳跃格子2
public int jump(int[] nums) {
int pos=nums.length-1;
int step=0;
while(pos>0){
for(int i=0;i<pos;i++){
if(i+nums[i]>=pos){
pos=i;
step++;
break;
}
}
}
return step;
}
70、划分字母区间
public List<Integer> partitionLabels(String s) {
int [] last=new int[26];
int length=s.length();
for(int i=0;i<length;i++){
last[s.charAt(i)-'a']=i;
}//把26个字母中对应字符串中的最远位置记录下来
List<Integer> res=new ArrayList<>();
int start=0;
int end=0;
for(int i=0;i<length;i++){
end=Math.max(end,last[s.charAt(i)-'a']);
if(i==end){//在这之前出现过的,仍然没有更大的end,
//此时就说明到达了终点
res.add(end-start+1);
start=end+1;
}
}
return res;
}
回溯
71、子集
class Solution {
List<List<Integer>> res=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
back(nums,0);
return res;
}
public void back(int[] nums,int start){
res.add(new ArrayList<>(path));
for(int i=start;i<nums.length;i++){
//元素是无序的,取过的元素不会重复取,for从start开始
path.add(nums[i]);
back(nums,i+1);//元素不重复取
path.removeLast();
}
}
}
72、分割回文串
class Solution {
List<List<String>> res=new ArrayList<>();
List<String> cur=new ArrayList<>();
public List<List<String>> partition(String s) {
back(s,0,new StringBuilder());
return res;
}
public void back(String s,int start,StringBuilder sb){
if(start==s.length()){
res.add(new ArrayList<>(cur));
return ;
}
for(int i=start;i<s.length();i++){
sb.append(s.charAt(i));
if(check(sb)){
cur.add(sb.toString());
back(s,i+1,new StringBuilder());
cur.remove(cur.size()-1);
}
}
}
public boolean check(StringBuilder sb){
for(int i=0;i<sb.length()/2;i++){
if(sb.charAt(i)!=sb.charAt(sb.length()-1-i)){
return false;
}
}
return true;
}
}
73、电话号码的字母组合
class Solution {
List<String> res=new ArrayList<>();
public List<String> letterCombinations(String digits) {
if(digits==null||digits.length()==0){
return res;
}
String[] arr={"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
back(digits,arr,0);
return res;
}
StringBuilder temp=new StringBuilder();
public void back(String digits,String[] arr,int index){
if(index==digits.length()){
res.add(temp.toString());
return;
}
String str=arr[digits.charAt(index)-'0'];
for(int i=0;i<str.length();i++){
temp.append(str.charAt(i));
back(digits,arr,index+1);
temp.deleteCharAt(temp.length()-1);
}
}
}
74、组合总和
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(candidates);
back(res,new ArrayList<>(),candidates,target,0,0);
return res;
}
public void back(List<List<Integer>> res,List<Integer> path,int[] candidates,int target,int sum,int index){
//一个集合求组合,需要index
if(sum==target){
res.add(new ArrayList<>(path));
return;
}
for(int i=index;i<candidates.length;i++){
if(sum+candidates[i]>target) break;
path.add(candidates[i]);
back(res,path,candidates,target,sum+candidates[i],i);
//元素可以重复选取,所以是i
path.remove(path.size()-1);
}
}
}
75、括号生成
class Solution {
StringBuilder track=new StringBuilder();
List<String> res=new ArrayList<>();
public List<String> generateParenthesis(int n) {
if(n==0){
return res;
}
back(n,n);
return res;
}
public void back(int left,int right){//左右括号剩余的数量
if(right<left) return;
if(left<0||right<0) return;
if(left==0&&right==0){
res.add(track.toString());
return;
}
track.append('(');
back(left-1,right);
track.deleteCharAt(track.length()-1);
track.append(')');
back(left,right-1);
track.deleteCharAt(track.length()-1);
}
}
76、单词搜索
class Solution {
public boolean exist(char[][] board, String word) {
char[] words=word.toCharArray();
for(int i=0;i<board.length;i++){
for(int j=0;j<board[0].length;j++){
if(dfs(board,words,i,j,0)) return true;
}
}
return false;
}
public boolean dfs(char[][]board,char[] word,int i,int j,int k){
if(i>=board.length||i<0||j>=board[0].length||j<0||board[i][j]!=word[k])
return false;
if(k==word.length-1) return true;
board[i][j]=' ';//
boolean res=dfs(board,word,i+1,j,k+1)||
dfs(board,word,i-1,j,k+1)||
dfs(board,word,i,j+1,k+1)||
dfs(board,word,i,j-1,k+1);
board[i][j]=word[k];//还原至当前初始值
return res;
}
}
77、全排列
class Solution {
List<List<Integer>> res=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
int n=nums.length;
if(n==0) return res;
back(nums,path);
return res;
}
public void back(int [] nums,LinkedList<Integer> path){
//排列是有序的,处理排列就不用start了
if(path.size()==nums.length){
res.add(new ArrayList<>(path));
}
for(int i=0;i<nums.length;i++){
if(path.contains(nums[i])) continue;
path.add(nums[i]);
back(nums,path);
path.removeLast();
}
}
}
技巧
78、只出现一次的数字
79、多数元素
80、颜色分类
81、下一个排列
class Solution {
public void nextPermutation(int[] nums) {
int i=nums.length-2;
while(i>=0&&nums[i]>=nums[i+1]){
i--;
}
if(i>=0){
int j=nums.length-1;
while(j>=0&&nums[i]>=nums[j]){
j--;
}
swap(nums,i,j);
}
reverse(nums,i+1);
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void reverse(int[] nums, int start) {
int left = start, right = nums.length - 1;
while (left < right) {
swap(nums, left, right);
left++;
right--;
}
}
}