文章目录
- 会议室
- 非那波切数列类问题
- 求最长的回文子串
- 找到字符串最长的无重复子串
- 最长公共子串
- 有效的匹配括号
- 2.求1+2+3+..+n
- 3.不用+-*/做加法
- 5.剪绳子
- 7.求一个整数其二进制中1的个数
- 8.用双指针反转链表
- 9.找到数组中消失的数字
- 12.三数之和
- 13.第n个丑数
- 14.实现Pow(x,n)函数
- 15.sqrt(int x)函数
- 质数相关
- 16.连续子数组的最大和
- 18.栈的压入,弹出序列
- 打印出最小数
- JZ65
- JZ66
- 丑数、质因数
- 岛屿数量&&DFS
- 找出最大正方形的面积
- 滑动窗口最大值plus
- 除自身以外数组的乘积
- 最短连续无序子数组
- 下一个排列
- 152.乘积最大子数组
- 搜索二维矩阵的一种巧妙方法
- 任务调度器
- 接雨水
- 最小覆盖子串
- 406. 根据身高重建队列
会议室
public int minMeetingRooms(int[][] intervals) {
if (intervals.length == 0) return 0;
//数组intervals[i][0]表示第i个会议的开始时间
//数组intervals[i][1]表示第i个会议的结束时间
// 默认小根堆
PriorityQueue<Integer> allocator = new PriorityQueue<>();
// 对时间表按照开始时间从小到大排序
Arrays.sort(intervals, new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return a[0] - b[0];
}
});
// 添加第一场会议的结束时间
allocator.add(intervals[0][1]);
// 遍历除第一场之外的所有会议
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] >= allocator.peek()) {
// 如果当前会议的开始时间大于前面已经开始的会议中最晚结束的时间
// 说明有会议室空闲出来了,可以直接重复利用
// 当前时间已经是 intervals[i][0],因此把已经结束的会议删除
allocator.poll();
}
// 把当前会议的结束时间加入最小堆中
allocator.add(intervals[i][1]);
}
// 当所有会议遍历完毕,还在最小堆里面的,说明会议还没结束,此时的数量就是会议室的最少数量
return allocator.size();
}
}
非那波切数列类问题
兔子生孩子问题,跳台阶问题
F(n)=F(n-1)+F(n-2)
子串系列
求最长的回文子串
class Solution {
public String longestPalindrome(String s) {
int len=s.length();
if(len<2)
return s;
int maxLen=1;
int begin=0;
boolean [][] dp=new boolean[len][len];
for(int k=0;k<len;k++){
for(int j=0;j<=k;j++){
if(s.charAt(j)!=s.charAt(k))
dp[j][k]=false;
else{
if(k<j+3)
dp[j][k]=true;
else
dp[j][k]=dp[j+1][k-1];
}
if(dp[j][k]&&k-j+1>maxLen){
maxLen=k-j+1;
begin=j;
}
}
}
return s.substring(begin,begin+maxLen);
}
}
找到字符串最长的无重复子串
import java.util.*;
import java.math.*;
public class Solution {
public int maxLength (int[] arr) {
if(arr.length < 2)
return arr.length;
HashMap<Integer,Integer> map = new HashMap<>();
int res = 1;
for(int start=0, end=0; end < arr.length; end++){、
/*当某个数在之前出现过,这个时候就把子串的起点start往后推一个,但是有一种情况,
比如1,2,3,4,3,5,1。到第二个3时,以后的子串起点start为4,
到第二个1时,如果不取最大的start,按start = map.get(arr[end])+1
算出起点start为2,显然以起点start=2,结尾end=1的子串234351有重复的,
因此start要取最大的
*/
if(map.containsKey(arr[end])){
start = Math.max(start,map.get(arr[end])+1);
}
res = Math.max(res,end-start+1);
map.put(arr[end],end);
}
return res;
}
}
最长公共子串
import java.util.*;
public class Solution {
public String LCS (String str1, String str2) {
int m = str1.length(), n = str2.length();
//dp[i][j]代表str1[0~m-1]和str2[0~n-1]的最大公共子串的长度
int[][] dp = new int[m + 1][n + 1];
int max = 0, index = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (str1.charAt(i) == str2.charAt(j)) {
dp[i + 1][j + 1] = dp[i][j] + 1;
if (max < dp[i + 1][j + 1]) {
max = dp[i + 1][j + 1];
index = i + 1;
}
}
}
}
return max == 0 ? "-1" : str1.substring(index-max,index);
}
}
dp[i][j]代表str1[0~m]和str2[0-n]的最大公共子串的长度,这里要求公共子串必须以str1[m]=str2[n]结尾
其他系列
有效的匹配括号
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
char[] chars = s.toCharArray();
//遍历所有的元素
for (char c : chars) {
//如果是左括号,就把他们对应的右括号压栈
if (c == '(') {
stack.push(')');
} else if (c == '{') {
stack.push('}');
} else if (c == '[') {
stack.push(']');
} else if (stack.isEmpty() || stack.pop() != c) {
//否则就只能是右括号。
//1,如果栈为空,说明括号无法匹配。
//2,如果栈不为空,栈顶元素就要出栈,和这个右括号比较。
//如果栈顶元素不等于这个右括号,说明无法匹配,
//直接返回false。
return false;
}
}
2.求1+2+3+…+n
要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。这里我们使用递归,用短路与作为结束递归的判断条件
public class Solution {
public int Sum_Solution(int n) {
boolean flag=(n>1)&&((n+=Sum_Solution(n-1))>0);
return n;
}
}
3.不用±*/做加法
通过位运算实现,有以下规律概括为:两个二进制的相加结果是用一个异或门实现的;两个二进制的进位结果是用一个与门和向左进位来实现的
public class Solution {
public int Add(int num1, int num2) {
int result, ans;
do {
result = num1 ^ num2; // 每一位相加
ans = (num1 & num2) << 1; // 进位
num1 = result;
num2 = ans;
} while (ans != 0);
return result;
}
}
5.剪绳子
题目:
给你一根长度为n的绳子,请把绳子剪成整数长的m段,每段绳子长度乘起来的乘积最大为?
public class Solution {
public int cutRope(int target) {
//当target=2,3时结果显而易见
if(target==2)
return 1;
if(target==3)
return 2;
//当target>3时,dp[i]代表i长度的子绳能分割出来的最大乘积
int[] dp=new int[target+1];
dp[1]=1;
当子绳长度为2时,不再拆分时乘积最大
dp[2]=2;
//当子绳长度为3时,不再拆分时乘积最大
dp[3]=3;
int max=0;
//dp[i]=dp[j]*dp[i-j]所有可能出现情况的最大值
for(int i=4;i<=target;i++){
for(int j=1;j<=i/2;j++){
max=Math.max(max,dp[j]*dp[i-j]);
}
dp[i]=max;
}
return dp[target];
}
}
7.求一个整数其二进制中1的个数
思路:
val :1101000, val-1: 1100111 那么val & (val-1) : 1100000,则val中有多少个1就可做多少次这个操作
public int countBit(int n){
int count=0;
while (n!=0){
count++;
n=n&(n-1);
}
return count;
}
进阶:
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。用上述方法复杂度较大,可以利用以下思路:一个数i假如是偶数,那么它二进制中1的个数等于i/2中1的个数,i假如是奇数,那么1的个数等于i/2中1的个数+1
class Solution {
public int[] countBits(int num) {
int[] bits = new int[num + 1];
for (int i = 1; i <= num; i++) {
//一个数的比特位1的个数先让他等于他一半的比特位量
bits[i] = bits[i / 2];
//如果是奇数还要加1
if ((i & 1) == 1)
bits[i]++;
}
return bits;
}
}
8.用双指针反转链表
题目:
反转一个单链表
public ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode cur=head;
ListNode tmp=null;
while(cur!=null){
tmp=cur.next;
cur.next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
9.找到数组中消失的数字
题目:
给定一个整型数组,其中1 ≤ a[i] ≤ n ( n = 数组大小 ),数组中的元素一些出现了两次,另一些只出现一次。找到所有在 [1, n] 范围之间没有出现在数组中的数字。
public List<Integer> findDisappearedNumbers(int[] nums) {
int len=nums.length;
for(int i=0;i<len;i++){
/*记录出现的数字index,然后将nums[index]+n,最后判断nums[i]<=n,
此时的i就是没有出现的数字*/
//考虑到数组越界的问题需要将i+1然后再-1;
int index=(nums[i]-1)%len;
nums[index]+=len;
}
ArrayList<Integer> list=new ArrayList<>();
for(int i=0;i<len;i++){
if(nums[i]<=len){
list.add(i+1);
}
}
return list;
}
12.三数之和
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result=new ArrayList<>();
int len=nums.length;
if(len<3)return result;
//对数组进行排序
Arrays.sort(nums);
//设置两个指针,分别从左,从右遍历,去重
int left=0,right=len-1;
for(int i=0;i<len;i++){
//数组已经排序,nums[i]>0则三数之和>0
if(nums[i]>0)break;
//去重
if(i>0&&nums[i]==nums[i-1])continue;
left=i+1;
right=len-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum==0){
//将结果添加进result
result.add(Arrays.asList(nums[i],nums[left],nums[right]));
//去重
while(left<right&&nums[left]==nums[left+1])left++;
while(left<right&&nums[right]==nums[right-1])right--;
//没有重复,指针各走一步
left++;
right--;
}else if(sum<0)
left++;
else if(sum>0)
right--;
}
}
return result;
}
13.第n个丑数
题目:
编写一个程序,找出第 n 个丑数。
一个丑数成以2/3/5,得到的还是一个丑数;有3个对列p2/p3/p5,每次都取最小的数,
public int nthUglyNumber(int n) {
if(n<0)
return 0;
int[] dp=new int[n];
dp[0]=1;
int p2=0,p3=0,p5=0;
int min;
for(int i=1;i<n;i++){
min=Math.min(dp[p2]*2,Math.min(dp[p3]*3,dp[p5]*5));
if(min==dp[p2]*2)
p2++;
if(min==dp[p3]*3)
p3++;
if(min==dp[p5]*5)
p5++;
dp[i]=min;
}
return dp[n-1];
}
14.实现Pow(x,n)函数
思路:
public double myPow(double x, int n) {
return n>0?helpMyPow(x,n):1.0/helpMyPow(x,n);
}
public double helpMyPow(double x,int n){
if(n==0)
return 1.0;
double y=helpMyPow(x,n/2);
return n%2==0?y*y:y*y*x;
}
15.sqrt(int x)函数
题目:
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去
思路:
使用二分法找到y*y<=x,最大的y值
public int mySqrt(int x) {
// 注意:针对特殊测试用例,例如 2147395599
// 要把搜索的范围设置成长整型
// 为了照顾到 0 把左边界设置为 0
long left = 0;
// # 为了照顾到 1 把右边界设置为 x // 2 + 1
long right = x / 2 + 1;
while (left < right) {
// 注意:这里一定取右中位数,如果取左中位数,代码会进入死循环
// long mid = left + (right - left + 1) / 2;
long mid = (left + right + 1)/2;
long square = mid * mid;
if (square > x) {
right = mid - 1;
} else {
left = mid;
}
}
// 因为一定存在,因此无需后处理
return (int) left;
}
质数相关
判断num是否为质数
质因子分解,将num分解为质因子并打印
这里借鉴上题的思想,如果遍历到Math.sqrt(num)还没发现其质因子,则可断定num本身为一个质数
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
long num=sc.nextLong();
long k=(long)Math.sqrt(num);
for(int i=2;i<=k;i++){
while(num%i==0){
System.out.print(i+" ");
num=num/i;
}
}
System.out.println(num==1?"":num+" ");
}
}
16.连续子数组的最大和
题目:
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值
public int FindGreatestSumOfSubArray(int[] array) {
if(array==null|array.length==0)
return 0;
int[] dp=new int[array.length];
dp[0]=array[0];
int max=dp[0];
for(int i=1;i<array.length;i++){
dp[i]=Math.max(array[i],dp[i-1]+array[i]);
max=Math.max(max,dp[i]);
}
return max;
}
题目升级<环形数组>
如果此时数组是一个环形数组,首尾相连,求连续子数组的最大值
思路:1.不考虑环形时:用动态规划求出连续子数组最大值max(dp[i])
2.考虑环形时:用数组总和sum-min(dp[i])
public int FindGreatestSumOfSubArray(int[] array) {
if(array==null|array.length==0)
return 0;
int sum=0;
for(int j=0;j<array.length;j++){
sum+=array[j];
}
/*考虑到我们并不需要所有dp[i]的值,
只需要最大最小值,所以只需要一个变量接收数据并及时更新即可
*/
int dpMax=array[0];
int max=array[0];
int dpMin=array[0];
int min=array[0];
for(int i=1;i<array.length;i++){
dpMax = Math.max(dpMax + array[i], array[i]);
max = Math.max(max, dpMax);
dpMin = Math.min(dpMin + array[i], array[i]);
min = Math.min(min, dpMin);
}
return Math.max(max,sum-min);
}
18.栈的压入,弹出序列
非常妙的方法,得背会
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length==0)
return false;
Stack<Integer> stack=new Stack<>();
int j=0;
for(int i=0;i<pushA.length;i++){
stack.push(pushA[i]);
while(!stack.isEmpty()&&stack.peek()==popA[j]){
stack.pop();
j++;
}
}
return stack.isEmpty();
}
}
打印出最小数
比较两个字符串s1, s2大小的时候,先将它们拼接起来,比较s1+s2,和s2+s1那个大,如果s1+s2大,那说明s2应该放前面,所以按这个规则,s2就应该排在s1前面
public String PrintMinNumber(int [] numbers) {
if(numbers.length==0||numbers==null)return "";
for(int i=0;i<numbers.length-1;i++){
for(int j=i+1;j<numbers.length;j++){
String s1=numbers[i]+""+numbers[j];
String s2=numbers[j]+""+numbers[i];
if(s1.compareTo(s2)>0){
int temp=numbers[i];
numbers[i]=numbers[j];
numbers[j]=temp;
}
}
}
String res="";
for(int k=0;k<numbers.length;k++){
res+=numbers[k];
}
return res;
}
JZ65
题目:
思路:
采用递归的方法,注意判断好边界问题
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
if(matrix==null||matrix.length==0)
return false;
int[] flag=new int[rows*cols];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(help(i,j,0,matrix,str,rows,cols,flag))
return true;
}
}
return false;
}
public boolean help(int i,int j,int cur,char[] matrix,char[] str,int rows,int cols,int[] flag){
//cur为数组str的索引,flag记录该位置是否被访问
int index=i*cols+j;//matrix的索引
if(i>=0&&i<rows&&j>=0&&j<cols&&flag[index]==0){
if(matrix[index]==str[cur]){
cur++;
//str遍历完毕,可以找到该路径
if(cur>=str.length)
return true;
//该节点被访问过
flag[index]=1;
if(help(i-1,j,cur,matrix,str,rows,cols,flag)||
help(i+1,j,cur,matrix,str,rows,cols,flag)||
help(i,j-1,cur,matrix,str,rows,cols,flag)||
help(i,j+1,cur,matrix,str,rows,cols,flag)){
return true;
}
//该节点不符合条件,重新设置为未访问
flag[index]=0;
return false;
}
return false;
}
return false;
}
}
JZ66
题目:
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
思路:
首先在某个节点处,要调用递归来决定某个位置的下一步去哪,此时有4个选择,每个选择都会进入下一个递归调用。当进入某个位置时,应当标记这个位置已访问过,避免之后又来到这里。在递归方法中,首先判断边界条件以及题目中所提的要求是否满足,都没问题,说明该位置可以访问,然后改变对应位置的标记。然后就是以该节点为中心,考虑下一步怎么走,本题就是4种走法,可以分开写,也可以一起写,由于本题是计数,所以就直接加在一起。然后return这些求和结果再+1,求和结果是下一步走的结果,而+1是本次访问此时的节点的次数。
public class Solution {
private int count=0;
public void helper(int i,int j,int rows,int cols,int[][] flag,int threshold){
//不符合条件就直接返回
if(i<0||i>=rows||j<0||j>=cols||flag[i][j]==1)return;
if(sum(i)+sum(j)>threshold){
flag[i][j]=1;
return;
}
flag[i][j]=1;
count++;
helper(i-1,j,rows,cols,flag,threshold);
helper(i+1,j,rows,cols,flag,threshold);
helper(i,j-1,rows,cols,flag,threshold);
helper(i,j+1,rows,cols,flag,threshold);
}
public int sum(int i){
int res=0;
while(i!=0){
res+=i%10;
i=i/10;
}
return res;
}
public int movingCount(int threshold, int rows, int cols)
{
int[][] flag=new int[rows][cols];
helper(0,0,rows,cols,flag,threshold);
return count;
}
}
<font color=#FF0033 size=7 face="黑体">找规律例题</font>
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210319202105271.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZsYXNoZG9nOA==,size_16,color_FFFFFF,t_70#pic_center)
思路:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210319202211700.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZsYXNoZG9nOA==,size_16,color_FFFFFF,t_70#pic_center)
```java
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNextInt()){
int i=sc.nextInt();
if(i<=2)
System.out.println(-1);
if(i%4==3||i%4==1)
System.out.println(2);
else if(i%4==0)
System.out.println(3);
else if(i%4==2)
System.out.println(4);
}
}
}
丑数、质因数
题目:
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路:
一个丑数成以2/3/5,得到的还是一个丑数;有3个对列p2/p3/p5,每次都取最小的数,放到数组中。
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index<=0)return 0;
int p2=0,p3=0,p5=0;
int[]result=new int[index];
result[0]=1;
for(int i=1;i<index;i++){
result[i]=Math.min(result[p2]*2,Math.min(result[p3]*3,result[p5]*5));
if(result[i] == result[p2]*2)p2++;//为了防止跳过丑数需要三个if都能够走到
if(result[i] == result[p3]*3)p3++;
if(result[i] == result[p5]*5)p5++;
}
return result[index-1];
}
}
岛屿数量&&DFS
class Solution {
public int numIslands(char[][] grid) {
if(grid==null||grid.length==0)return 0;
int row=grid.length;
int col=grid[0].length;
int res=0;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(grid[i][j]=='1'){
res++;
dfs(grid,i,j,row,col);
}
}
}
return res;
}
public void dfs(char[][] grid,int i,int j,int row,int col){
if(i<0||j<0||i>=row||j>=col||grid[i][j]=='0')
return;
grid[i][j]='0';
dfs(grid,i+1,j,row,col);
dfs(grid,i,j+1,row,col);
dfs(grid,i-1,j,row,col);
dfs(grid,i,j-1,row,col);
}
}
找出最大正方形的面积
public int maximalSquare(char[][] matrix) {
int row=matrix.length;
int col=matrix[0].length;
if(row==0||col==0)return 0;
int maxSide=0;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(matrix[i][j]=='1'){
maxSide=Math.max(maxSide,1);
int maxLen=Math.min(row-i,col-j);
for(int k=1;k<maxLen;k++){
int flag=0;
if(matrix[i+k][j+k]=='0'){
break;
}
for(int m=0;m<k;m++){
if(matrix[i+m][j+k]=='0'||matrix[i+k][j+m]=='0'){
flag=1;
break;
}
}
if(flag==0){
maxSide=Math.max(maxSide,k+1);
}else
break;
}
}
}
}
return maxSide*maxSide;
}
滑动窗口最大值plus
- 采用优先队列,重写compare,每次队列头部都是最大值
- 队列中存储的为数组[num,index]。index用于判断滑动窗口的边界,使不在窗口范围的元素poll()
import java.util.*;
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
Queue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] != o2[0] ? o2[0] - o1[0] : o2[1] - o1[1];
}
});
if(nums.length<k)return null;
int[] res=new int[nums.length-k+1];
for(int i=0;i<k;i++){
queue.offer(new int[]{nums[i],i});
}
res[0]=queue.peek()[0];
for(int i=k;i<nums.length;i++){
queue.offer(new int[]{nums[i],i});
//判断边界,不在窗口范围的元素poll
while(queue.peek()[1]<=i-k){
queue.poll();
}
res[i-k+1]=queue.peek()[0];
}
return res;
}
}
除自身以外数组的乘积
这里要求时间复杂度为O(n),对于每一个output[i],我们都可以取得他左边所有元素的乘积和右边所有元素的乘积,最后即可得到除去他本身所有元素的乘积
public int[] productExceptSelf(int[] nums) {
int[] res = new int[nums.length];
//nums[i]左边所有元素的乘积
int[] L = new int[nums.length];
//nums[i]右边所有元素的乘积
int[] R = new int[nums.length];
L[0] = 1;
for (int i = 1; i < nums.length; i++) {
L[i] = L[i - 1] * nums[i - 1];
}
R[nums.length - 1] = 1;
for (int i =nums.length-2; i>=0; i--) {
R[i] = R[i + 1] * nums[i + 1];
}
for (int i = 0; i < nums.length; i++) {
res[i] = L[i] * R[i];
}
return res;
}
最
最短连续无序子数组
将数组排序后和原数组对比,找到第一个不相同数的位置和最后一个不相同数的位置,俩位置之差即为长度
public int findUnsortedSubarray(int[] nums) {
if(nums.length==0)return 0;
int[] nums1=Arrays.copyOf(nums,nums.length);
Arrays.sort(nums);
int start=0;
int end=0;
int flag=0;
for(int i=0;i<nums.length;i++){
if(nums[i]!=nums1[i]){
if(flag==0)
start=i;
else
end=i;
flag++;
}
}
if(flag==0)return 0;
return end-start+1;
}
下一个排列
public void nextPermutation(int[] nums) {
if(nums.length<=1)return;
int i=nums.length-2;
while(i>=0&&nums[i]>=nums[i+1])
i--;
if(i>=0){
int j=nums.length-1;
while(j>i&&nums[j]<=nums[i])
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;
int right=nums.length-1;
while(left<right){
swap(nums,left,right);
left++;
right--;
}
}
152.乘积最大子数组
public int maxProduct(int[] nums) {
if(nums.length==0)return 0;
int imax=1;
int imin=1;
int max=Integer.MIN_VALUE;
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;
}
搜索二维矩阵的一种巧妙方法
注意递增规律,从左下角开始比较,比target小则右移,大则上移
public boolean searchMatrix(int[][] matrix, int target) {
// start our "pointer" in the bottom-left
int row = matrix.length-1;
int col = 0;
while (row >= 0 && col < matrix[0].length) {
if (matrix[row][col] > target) {
row--;
} else if (matrix[row][col] < target) {
col++;
} else { // found it
return true;
}
}
return false;
}
任务调度器
public int leastInterval(char[] tasks, int n) {
int len=tasks.length;
if(len==0)return 0;
int[] count=new int['Z'+1];
for(int i=0;i<len;i++){
count[tasks[i]]++;
}
int maxTime=0;
for(int i='A';i<='Z';i++){
maxTime=Math.max(maxTime,count[i]);
}
int maxCount=0;
for(int i='A';i<='Z';i++){
if(count[i]==maxTime)
maxCount++;
}
return Math.max((maxTime-1)*(n+1)+maxCount,len);
}
接雨水
public int trap(int[] height) {
if(height.length==0)return 0;
int ans=0;
for(int i=1;i<height.length-1;i++){
int maxLeft=0;
int maxRight=0;
for(int j=i;j>=0;j--){
maxLeft=Math.max(maxLeft,height[j]);
}
for(int j=i;j<height.length;j++){
maxRight=Math.max(maxRight,height[j]);
}
ans+=Math.min(maxRight,maxLeft)-height[i];
}
return ans;
}
最小覆盖子串
Map<Character, Integer> ori = new HashMap<Character, Integer>();
Map<Character, Integer> cnt = new HashMap<Character, Integer>();
public String minWindow(String s, String t) {
int tLen = t.length();
for (int i = 0; i < tLen; i++) {
char c = t.charAt(i);
ori.put(c, ori.getOrDefault(c, 0) + 1);
}
int l = 0, r = -1;
int len = Integer.MAX_VALUE, ansL = -1, ansR = -1;
int sLen = s.length();
while (r < sLen) {
++r;
if (r < sLen && ori.containsKey(s.charAt(r))) {
cnt.put(s.charAt(r), cnt.getOrDefault(s.charAt(r), 0) + 1);
}
while (check() && l <= r) {
if (r - l + 1 < len) {
len = r - l + 1;
ansL = l;
ansR = r+1;
}
if (ori.containsKey(s.charAt(l))) {
cnt.put(s.charAt(l), cnt.get(s.charAt(l)) - 1);
}
++l;
}
}
return ansL == -1 ? "" : s.substring(ansL, ansR);
}
public boolean check() {
Iterator iter = ori.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Character key = (Character) entry.getKey();
Integer val = (Integer) entry.getValue();
if (cnt.getOrDefault(key, 0) < val) {
return false;
}
}
return true;
}
406. 根据身高重建队列
import java.util.*;
class Solution {
public int[][] reconstructQueue(int[][] people) {
int row=people.length;
int col=people[0].length;
Arrays.sort(people,new Comparator<int[]>(){
public int compare(int[] o1,int[] o2){
if(o1[0]==o2[0])
return o1[1]-o2[1];
return o2[0]-o1[0];
}
});
List<int[]> list=new ArrayList<>();
for(int[] arr:people){
list.add(arr[1],arr);
}
return list.toArray(new int[list.size()][2]);
}
}