欢迎各位关注我的公众号,会继续更新算法知识与前后端知识
1.题目:
给定正整数 n ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。
数字排序后进行匹配,不需要对n里的数字进行不断排序,可以判断n与2次方的数(同样长度)进行sort排序后n是否包含在这些被排序后的2次方的数里面
class Solution {
public boolean reorderedPowerOf2(int n) {
Set set = new HashSet<>();
for(int i = 1;i > 0;i <<= 1) {
set.add(isS(i));
}
return set.contains(isS(n));
}
public String isS(int x) {
char[] arr = String.valueOf(x).toCharArray();
Arrays.sort(arr);
return new String(arr);
}
}
2.题目:
我们定义「顺次数」为:每一位上的数字都比前一位上的数字大 1 的整数。
请你返回由 [low, high] 范围内所有顺次数组成的 有序 列表(从小到大排序)。
示例:输出:low = 100, high = 300
输出:[123,234]
暴力枚举超时
dfs:
class Solution {
public List sequentialDigits(int low, int high) {
List list = new ArrayList<>();
for(int i = 1;i <= 9;i++) {
dfs(list,i,i,low,high);
}
//[1234,12345,2345,3456,4567,5678,6789] 这样的例子是错误的,所以需要排序
Collections.sort(list);
return list;
}
public void dfs(List list,int a,int c,int low,int high) {
//a=待判断是否符合的数字
//c=为a准备末尾数字
//边界条件,数已经大于high
if(a > high)
return;
//往集合里面添加符合条件的数字
if(a >= low)
list.add(a);
//在符合条件的数字中,9是数字最后一位的最大值
if(c == 9)
return;
dfs(list,a * 10 + c + 1,c+1,low,high);
}
}
3.题目
把符合下列属性的数组 arr 称为 山脉数组 :arr.length >= 3
存在下标 i(0 < i < arr.length - 1),满足
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
给出一个整数数组 arr,返回最长山脉子数组的长度。如果不存在山脉子数组,返回 0 。
示例 :
输入:arr = [2,1,4,7,3,2,5]
输出:5
解释:最长的山脉子数组是 [1,4,7,3,2],长度为 5。
pass:一开始的思路是定义2个常量为0,因为只能一次升一次降,而且必须先升才能降,所以必须升的那个常量++才能降,但不实在
class Solution {
public int longestMountain(int[] arr) {
int len = arr.length;
int count = 0;
for(int i = 1;i < len - 1;i++) {
//从中间元素开始
if(arr[i] > arr[i-1] && arr[i] > arr[i+1]) {
int j = i - 1;
int x = i + 1;
while(j > 0) {
if(arr[j] > arr[j-1]) {
j--;
}else {
break;
}
}
while(x < len-1) {
if(arr[x] > arr[x+1]) {
x++;
}else {
break;
}
}
count = Math.max(count,x-j+1);
}
}
return count;
}
}
4.题目:跳跃游戏1
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
思路:可以不断更新能达到的最远距离,用一个for循环从第一个元素开始便利,前提是能走到。
示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
class Solution {
public boolean canJump(int[] nums) {
int len = nums.length;
//记录能到达的最远的地方
int max = 0;
//i记录的是目前在第几个元素
for(int i = 0;i < len;i++) {
//只有满足i<=max才合理
//已知目前能去到的最远地方为max,则max之前的地方都能达到
if(i <= max) {
//不断更新最远距离
max = Math.max(max,i + nums[i]);
if(max >= len - 1)
return true;
}
}
return false;
}
}
5.题目:跳跃游戏2
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
思路:我们可以从反方向开始,判断当前位置能否到达终点(从第一个开始遍历,这样能、用最少的步数走最大的距离)。
示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
class Solution {
public int jump(int[] nums) {
int len = nums.length;
int posi = len - 1;
int step = 0;
while(posi > 0) {
for(int i = 0;i < len;i++) {
//能去到的(最少的步数走最远的地方)
if(i + nums[i] >= posi) {
step++;
//已经能去到终点了,现在只需要去到当前i位置
posi = i;
break;
}
}
}
return step;
}
}
6.题目:
给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。
玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 0 。每一回合,玩家从数组的任意一端取一个数字(即,nums[0] 或 nums[nums.length - 1]),取到的数字将会从数组中移除(数组长度减 1 )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。
如果玩家 1 能成为赢家,返回 true 。如果两个玩家得分相等,同样认为玩家 1 是游戏的赢家,也返回 true 。你可以假设每个玩家的玩法都会使他的分数最大化。
递归
class Solution {
public boolean PredictTheWinner(int[] nums) {
int len = nums.length;
return getBoo(nums,0,len-1,1) >= 0;
}
public int getBoo(int[] nums,int left,int right,int player) {
//递归出口
if(left == right)
return player * nums[left];
//先选左边的情况
int startLeft = nums[left] * player + getBoo(nums,left + 1,right,-player);
//先选右边的情况
int startRight = nums[right] * player + getBoo(nums,left,right - 1,-player);
if(player == 1){
//玩家一要最大的
return Math.max(scoreStart ,scoreEnd );
}else{
//玩家二要最小的
return Math.min(scoreStart ,scoreEnd );
}
}
}