dsadas
/**
思路:找下一个排列,并且尽可能小,所以我们应该找一序列中从左边开始的“较小值”与“较大值”交换,但是为了尽可能小应该满足:
1、“较小值”:应该尽可能靠右,并且“较小值”的右边子序列升序
2、“较大值”:这个较大值应该是“较小值”右边所有比他大的序列中的最小值
3、调换后,然后保证"较小值i处"右边是升序的 (此时i右边的数组是递减的)
4、注意:如果整个数组是递减的,则为该数组的最大值
123456 123465 123546 ... 654321
*/
class Solution {
public void nextPermutation(int[] nums) {
if(nums.length == 1) return ;
//首先找"较小值,该值是从右向左遍历的"较小值"
int i = nums.length-2 ;
while(i>=0 && nums[i] >= nums[i+1]){
i--;
}
//此时i+1开始的数组是递减的,若i为-1,说明数组是最大排序,则只有在i>=0的时候我们才能进行判断
int j = nums.length-1;
if(i>=0){
//找尽可能靠右边的大于"较小值"的最小的"较大值" (其实就是数组最后一个值)
while(j>=0 && nums[i]>= nums[j]){
j--;
}
//到此,"较小值" 和 "较大值" 就已经找到位置了,然后需要调换顺序
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
//这时候我们就要保证“较小值”右边是生效的,在这之前,[i+1,nums.length-1]是递减的,应该变换反转方向
//Arrays.sort(nums , i+1 , nums.length);
//当i=-1,说明此时数组是最大值,返回的是最小的数组排序,也可以表达为Arrays.sort(nums , i+1 , nums.length);
//因此放到外面
}
Arrays.sort(nums , i+1 , nums.length);
}
}
//换一种写法
class Solution {
public void nextPermutation(int[] nums) {
int len = nums.length;
for(int i=len-1 ; i>0 ; i--){
if(nums[i]>nums[i-1]){
Arrays.sort(nums,i,len); //"i-1"为较小值,此时我们先将"i-1"右边的数组排序
for(int j=i ; j<len ; j++){
if(nums[j] > nums[i-1]){
int temp = nums[j];
nums[j] = nums[i-1];
nums[i-1] = temp;
return;
}
}
}
}
Arrays.sort(nums); //为了对应数组的最大序返回的数组
return ;
}
}
//解法3:(和解法1差不多)
class Solution {
public void nextPermutation(int[] nums) {
//首先我们去找“较小值”
int i = nums.length-2;
while(i>=0 && nums[i]>=nums[i+1]){
i--;
}
//此时找到了“最靠右边”的“较小值”,然后我们去找"尽可能小的"“较大值”,也就是在“较小值”的
//右边序列中仅大于“较小值”的最大值
int j = nums.length-1;
//如果i<0,也就是-1,则说明这个数组正好是降序的,也就是这个数组可以表示的最大值
//所以我们在i>=0,的时候我们才进行交换
if(i>=0){
while(j>=0 && nums[i]>=nums[j]){
j--;
}
//此时就找到了我们想要的“较大值”的位置,然后让两个值交换
// 为了低耦合,我们用方法进行“交换”
swap(nums,i,j);
}
//这时候我们就要保证“较小值”右边是生效的,在这之前,[i+1,nums.length-1]是递减的,应该变换反转方向
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 l = start , r = nums.length-1;
while(l < r){
swap(nums,l,r);
l++;
r--;
}
}
}
dasdasd
//思路:如果不考虑时间复杂度0(n),可以先排序,然后滑动窗口。
//因为考虑时间复杂度,所以要换一种数学思想:“核心思想”:我们只要去找一个连续的当中得最小值开始求就可以,通过num,num-1判定
//1、优化:因为我们找连续的,所以可以通过set来去掉重复的数
//2、遍历数组,我们没必要每个数都找连续,如果当前数值-1不在set中,我们再去求连续,如果在则不用了
class Solution {
public int longestConsecutive(int[] nums) {
//创建set
Set<Integer> nums_set = new HashSet<Integer>();
//将数组放入到set中
for(int num : nums){
nums_set.add(num);
}
int longestCount = 0;
//遍历数组,看num-1是否在set中,如果在,就没必要去就最大连续,如果不在,就可以去求最大连续
for(int num : nums){
if(!nums_set.contains(num-1)){
//说明不包含num-1,则num是某个连续序列得最小值
int curNum = num;
int curCount = 1;
//求“num是某个连续序列得最小值”的连续序列得长度
while(nums_set.contains(curNum+1)){
curNum+=1;
curCount += 1;
}
longestCount = Math.max(longestCount,curCount);
}
}
return longestCount;
}
}
dasdas
//第一种方法,双重for循环,我记得会超时,所以不再写
/*
通过左右指针判断,通过一个变量存储水的面记 areaMax = Integer.MIN_VALUE
然后做右指针记录数值,往里面遍历,如果高变大了我们重新求面积,如果没有变大,则直接略过
时间复杂度O(n) 空间复杂度O(1)
*/
class Solution {
public int maxArea(int[] height) {
int l = 0 , r = height.length-1;
int maxArea = (r-l) * Math.min(height[l] , height[r]);
while(l<r){
if(height[l]<height[r]){
l++;
}else{
r--;
}
maxArea = Math.max(maxArea , (r-l)*Math.min(height[l],height[r]));
}
return maxArea;
}
}
//优化算法
class Solution {
public int maxArea(int[] height) {
int l = 0 , r = height.length-1 , maxArea = 0;
while(l<r){
maxArea = height[l] > height[r] ? Math.max(maxArea , (r-l)*height[r--]) : Math.max(maxArea , (r-l)*height[l++]);
}
return maxArea;
}
}
dasdads
//解题思路:“桶思想”:很奇妙的思想
//1、我们找几个桶子,大小是数组中最大重复字数的个数
//2、每个桶的容量是(n+1),这样可以保证每个桶都是不需要待命的,因此这种情况的全部时间就是(桶数-1)*(间隔数+1)+最后一个桶的任务个数
//3、第二种情况就是不需要待命,则总时间就是"tasks.length()""
class Solution {
public int leastInterval(char[] tasks, int n) {
//求一下数组的长度
int len = tasks.length;
//求一下最大个数的任务是什么,相同个数的任务有多少
int maxTask = 0 , maxCountTask = 0;
//创建放任务的数组,一共26个字母
int[] temp = new int[26];
//往里面存入数据
for(char c : tasks){
temp[c-'A']++; //存入数据
maxTask = Math.max(maxTask,temp[c-'A']);
}
for(int countTask : temp){
if(countTask == maxTask){
maxCountTask++;
}
}
return Math.max(len,(maxTask-1)*(n+1)+maxCountTask);
}
}