面试经典150题(21-26)

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;
    }
}

今天这些也是之前做过的,有印象所以做的还算是快,但是有些也忘的差不多了,总之比之前有一点点的提升,至少暴力求解能写出来了。

唉,最近又开始被催着相亲了,真不知道说什么。。直男的痛苦啊,真的想一句话,我真的能想一个小时,感觉比算法题还难。。
加油早日跳槽!!!

你可能感兴趣的:(面试经典,150,题,面试,职场和发展,算法)