leetcode 150道题 计划花两个月时候刷完,今天(第十二天《天数乱了》)完成了6道(21-26)150:
21.(28. 找出字符串中第一个匹配项的下标) 题目描述:
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
第一版(这个题有印象,KMP算法但是我不会,我只能写简单的版本比暴力强一点的)
class Solution {
public int strStr(String haystack, String needle) {
int hLen=haystack.length();
int nLen=needle.length();
int hIndex=0;
int nIndex=0;
while(hIndex<hLen&&nIndex<nLen){
if(haystack.charAt(hIndex)==needle.charAt(nIndex)){
hIndex++;
nIndex++;
}else{
// 这块回退只要记住就 OK
hIndex=hIndex-nIndex+1;
nIndex=0;
}
}
if(nIndex==nLen){
return hIndex-nIndex;
}else{
return -1;
}
}
}
22.(125. 验证回文串) 题目描述:
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
第一版(这个题我感觉只需要知道咋判断字符是不是数字和字母就会,isLetterOrDigit(char))
class Solution {
public boolean isPalindrome(String s) {
s=s.toLowerCase();
int left=0;int right=s.length()-1;
while(left<right){
while(left<right
&&!Character.isLetterOrDigit(s.charAt(left))){
left++;
}
while(left<right
&&!Character.isLetterOrDigit(s.charAt(right))){
right--;
}
if(s.charAt(left++)!=s.charAt(right--)){
return false;
}
}
return true;
}
}
23.(392. 判断子序列) 题目描述:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
第一版(这个直接写)
class Solution {
public boolean isSubsequence(String s, String t) {
int sLen=s.length();
int tLen=t.length();
if(sLen>tLen){
return false;
}
int sIndex=0;
int tIndex=0;
while(sIndex<sLen&&tIndex<tLen){
if(s.charAt(sIndex)==t.charAt(tIndex)){
sIndex++;
}
tIndex++;
}
return sIndex==sLen;
}
}
24.(167. 两数之和 II - 输入有序数组)题目描述:
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
第一版(这个是典型的双指针题目了)
class Solution {
public int[] twoSum(int[] numbers, int target) {
int left=0;
int right=numbers.length-1;
while(left<right){
int temp=numbers[left]+numbers[right];
if(temp==target){
return new int[]{left+1,right+1};
}else if(temp<target){
left++;
}else{
right--;
}
}
return new int[]{};
}
}
25.(11. 盛最多水的容器)题目描述:
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
第一版(这个真的没想到双指针,所以我就直接暴力了,但是加了一点点优化,暴力也是过了,暴力无敌)
class Solution {
public int maxArea(int[] height) {
int len=height.length;
// len 最小是2
if(len<=1)
return 0;
int max=0;
int maxHeight=-1;
for(int i=0;i<len-1;i++){
if(height[i]>maxHeight){
maxHeight=height[i];
}else{
continue;
}
for(int j=i+1;j<len;j++){
max=Math.max((j-i)*Math.min(height[i],height[j]),max);
}
}
return max;
}
}
第二版(看了解题,这题做了好几遍了但还是想不到双指针,我对双指针的印象停留在有序的数组上,这个是无序的但是看解题说最后是可以验证双指针是对的)
class Solution {
public int maxArea(int[] height) {
int len=height.length;
// len 最小是2
if(len<=1)
return 0;
int left=0;
int right=len-1;
int max=0;
int temp=0;
while(left<right){
if(height[left]>height[right]){
temp=height[right]*(right-left);
right--;
}else{
temp=height[left]*(right-left);
left++;
}
max=Math.max(temp,max);
}
return max;
}
}
26.(15. 三数之和)题目描述:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
第一版(这个也做了好几边,但是还是没注意题目,返回值要的值不是index,可以先排序然后就可以用双指针了,那就让大家看看我的骚操作,怎么过滤的。。)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int len=nums.length;
List<List<Integer>> res=new ArrayList();
if(len<=1)
return res;
Arrays.sort(nums);
Set<String> set=new HashSet();
int left=1;
int right=len-1;
for(int i=0;i<len-2;i++){
// 双指针
left=i+1;
right=len-1;
while(left<right){
int temp=nums[i]+nums[left]+nums[right];
if(temp==0){
StringBuilder sb=new StringBuilder();
sb.append(nums[i]);
sb.append(nums[left]);
sb.append(nums[right]);
if(set.add(sb.toString())){
res.add(Arrays.asList(nums[i],nums[left],nums[right]));
}
left++;
right--;
}else if(temp>0){
right--;
}else{
left++;
}
}
}
return res;
}
}
第二版(不得不说,去重的思想很厉害)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int len=nums.length;
List<List<Integer>> res=new ArrayList();
if(len<=2)
return res;
Arrays.sort(nums);
int left=1;
int right=len-1;
for(int i=0;i<len-2;i++){
// 去重
if(nums[i]>0)
continue;
if(i!=0){
if(nums[i]==nums[i-1])
continue;
}
// 双指针
left=i+1;
right=len-1;
while(left<right){
int temp=nums[i]+nums[left]+nums[right];
if(temp==0){
res.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(temp>0){
right--;
}else{
left++;
}
}
}
return res;
}
}
今天这些也是之前做过的,有印象所以做的还算是快,但是有些也忘的差不多了,总之比之前有一点点的提升,至少暴力求解能写出来了。
唉,最近又开始被催着相亲了,真不知道说什么。。直男的痛苦啊,真的想一句话,我真的能想一个小时,感觉比算法题还难。。
加油早日跳槽!!!