给你一个字符串
s
,找到s
中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
我们可以根据前面的子串结果,在头尾拼接上一个字符并判断其是否相同。DP
class Solution {
public String longestPalindrome(String s) {
int len=s.length();
int maxStart = 0;
int maxEnd = 0;
int maxLen = 1;
boolean[][] isReverse=new boolean[len][len];
for(int j=1;j<len;j++){
for(int i=0;i<len;i++){
//if(j-i+1
if((s.charAt(i)==s.charAt(j))&&((j-i<=2)||(isReverse[i+1][j-1]))){
isReverse[i][j]=true;
if(j-i+1>maxLen){
maxLen=j-i+1;
maxEnd=j;
maxStart=i;
}
}
else isReverse[i][j]=false;
}
}
return s.substring(maxStart,maxEnd+1);
}
}
注意第一层循环是右指针,第二层循环是左指针。这样才能用到前面的结果。
给你一个 32 位的有符号整数
x
,返回将x
中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围
[−231, 231 − 1]
,就返回 0。假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123 输出:321
翻转好做,但是有个要求:翻转后的数字大小超出了 int 范围则返回0.
我们用 long 存储翻转后的数字,如果 (int)res!=res
就返回0.
给定一个长度为
n
的整数数组height
。有n
条垂线,第i
条线的两个端点是(i, 0)
和(i, height[i])
。找出其中的两条线,使得它们与
x
轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。
**说明:**你不能倾斜容器。
如图,给定一个 height[] 数组,让我找到盛水最高的两条边。
思路:直接遍历超时。首先我们让左右指针到最左最右。算出当前面积。
然后我们左右指针往里挪,底边变短,那么我们必须想办法让 height 最小值增加才能有面积的提升,因此我们让最矮的 height 那边指针先动,比如上图就是右边红色指针先动。这样效率高。
找到三数求和=0的所有组合。不能重复。肯定是不能直接遍历,太慢了。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List resList=new ArrayList<List>();
int i=0,len=nums.length;
for(;i<len-2;i++){
if(i>0&&nums[i]==nums[i-1])continue;
int target=-nums[i];
for(int j=i+1;j<len-1;j++){
if(j>i+1&&nums[j]==nums[j-1])continue;
int k=len-1;
while(j<k&&nums[j]+nums[k]>target)k--;
if(j==k)break;
else if(nums[j]+nums[k]==target){
List subList=new ArrayList<Integer>();
subList.add(nums[i]);
subList.add(nums[j]);
subList.add(nums[k]);
resList.add(subList);
}
}
}
return resList;
}
}
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,
arr = [1,2,3]
,以下这些都可以视作arr
的排列:[1,2,3]
、[1,3,2]
、[3,1,2]
、[2,3,1]
。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
- 例如,
arr = [1,2,3]
的下一个排列是[1,3,2]
。- 类似地,
arr = [2,3,1]
的下一个排列是[3,1,2]
。- 而
arr = [3,2,1]
的下一个排列是[1,2,3]
,因为[3,2,1]
不存在一个字典序更大的排列。给你一个整数数组
nums
,找出nums
的下一个排列。必须** 原地 **修改,只允许使用额外常数空间。
主要就是算法。
class Solution {
public void swap(int[] nums, int i, int j){
nums[i]=nums[i]^nums[j];
nums[j]=nums[i]^nums[j];
nums[i]=nums[i]^nums[j];
}
public void reverse(int[] nums){
for(int i=0;i<=nums.length/2-1;i++){
swap(nums, i, nums.length-1-i);
}
}
public void nextPermutation(int[] nums) {
int len=nums.length;
int i=len-1;
while(i!=0&&!(nums[i-1]<nums[i])){
i--;
}
if(i==0)reverse(nums);
else {
i--;
int min=101;
for(int j=len-1;j>i;j--){
if(nums[j]<min&&nums[j]>nums[i]){
swap(nums, i, j);
Arrays.sort(nums,i+1,len);
return;
}
}
}
}
}
给你一个按照非递减顺序排列的整数数组
nums
,和一个目标值target
。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值
target
,返回[-1, -1]
。你必须设计并实现时间复杂度为
O(log n)
的算法解决此问题。示例 1:
输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]
是二分法,但是不完全是,因为我们要找到起始区间。
我们可以通过两次二分,第一次找起始位置或小于目标值的最大的数的位置;第二次找结束位置或大于目标值的最小数的位置。
class Solution {
public int[] searchRange(int[] nums, int target) {
int len=nums.length;
int[] res=new int[2];
res[0]=-1;
res[1]=-1;
int left=0,right=len-1;
while(left<=right){
int mid=(left+right)/2;
if(nums[mid]>=target){right=mid-1;res[0]=mid;}
else left=mid+1;
}
left=0;right=len-1;
while(left<=right){
int mid=(left+right)/2;
if(nums[mid]>target){right=mid-1;res[1]=mid;}
else left=mid+1;
}
res[1]=right;
if(!(res[0]<=res[1])||res[0]==-1||res[1]==-1){
res[0]=-1;
res[1]=-1;
}
return res;
}
}
如果数组中一定存在给定数,那么只靠两个 while 循环是可以找到起始和结束位置的。但是如果不存在,这两个循环查询可能会出现一些错误,比如一个是找到的位置,一个是-1;或者 right