码迷,mamicode.com
首页 > 其他好文 > 详细

Leecode——2021.04.17

时间:2021-04-19 15:40:01      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:需要   翻转单词顺序   most   stringbu   获得   处理   else   delete   null   

滑动窗口

219. 存在重复元素 II

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

// 滑动窗口做法

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        
        
        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; ++i) {
            if (set.contains(nums[i])) return true;
            set.add(nums[i]);
            if (set.size() > k) {
                set.remove(nums[i - k]);
            }
        }
        return false;

    }
}

// 我的做法 效率>98%

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer, Integer>map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            if(map.containsKey(nums[i])){
                int val = map.get(nums[i]);
                if(Math.abs(val - i) <= k){
                    return true;
                }
            }
           
            map.put(nums[i], i);
            
        }
        return false;
    }
}

220. 存在重复元素 III

给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在两个下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。

如果存在则返回 true,不存在返回 false。

官方解答:
x是nums[]里面的一个元素。 |x+y| <= t 那么只要满足 x - t <= y <= x + t所以给定一个区间[x-t, x+t]
然后因为还要满足 |i - j|下标 <= k那么我们使用一个滑动窗口(也就是一个队列,他的长度是k)
我们只需要找到 set集合中最接近abs(x-t)的那个值然后让其 <= x +t即可
如果size()>k移出首个元素,保证在集合set内的元素下标都满足k的要求

class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        int n = nums.length;
        // 使用long类型防止超界
        TreeSet<Long>set = new TreeSet<>();
        for(int i = 0; i < n; i++){
            // set.ceiling(key)寻找比比key大而且最接近key的值
            // 如果set中不存在的话,就返回null
            Long ceiling = set.ceiling((long)nums[i] - (long)t);// nums[i] - t
            if(ceiling != null && ceiling <= ((long)nums[i] + (long)t)){
                return true;// nums[i] + t
            }
            set.add((long)nums[i]);
            if(set.size() > k){
                set.remove((long)nums[i - k]);// set集合的大小超过了k就移出第一个元素
            }
        }
        return false;
    }
}

双指针

剑指 Offer 58 - I. 翻转单词顺序

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。

// Leecode大神的做法: 好像效率比下面的低一些

class Solution {
    public String reverseWords(String s) {
        
       
        // 先去除掉头尾空格
        s = s.trim();
        int n = s.length();
        int i = n - 1, j = n - 1;// 两个指针从后面向前遍历
        StringBuilder sb = new StringBuilder();
        while(i >= 0){
            // 遇见不是空格就向前移动
            while(i >= 0 && s.charAt(i) != ‘ ‘){
                i--;
            }

            sb.append(s.substring(i + 1, j + 1)).append(" ");

            // 跳过空格
            while(i >= 0 && s.charAt(i) == ‘ ‘){
                i--;
            }
            j = i;
        }
        return sb.toString().trim();
    }
}

// 我的做法:切分+拼接

class Solution {
    public String reverseWords(String s) {
        
        String[] str = s.split(" ");
        StringBuilder sb = new StringBuilder();
        // System.out.println(Arrays.toString(str));
        for(int i = str.length - 1; i >= 0; i--){
            if("".equals(str[i])){
                continue;
            }
            else{
                sb.append(str[i]).append(" ");
            }
        }
        // 删除掉最后一个元素 空格
        if(sb.length() > 0){
            return sb.deleteCharAt(sb.length() - 1).toString();
        }
        else{
            // 如果是空串 或者全部都是空格
            return "";
        }
        
    }
}

剑指 Offer 53 - II. 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

class Solution {
    public int missingNumber(int[] nums) {

        // 主要就是看下标和元素值是否对应
        for(int i = 0; i < nums.length; i++){
            if(nums[i] == i){
                continue;
            }
            else{
                return i;
            }
        }
        return nums.length;
    }
}

动态规划

剑指 Offer 47. 礼物的最大价值

在一个 m * n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

// 只能向下移动或者向左移动

class Solution {
    public int maxValue(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        // dp[i][j]表示到达第grid[i][j]这个位置时候可以获得的礼物最大价值
        // dp[i][j] = Math.max(dp[i - 1][j] + grid[i][j], dp[i][j - 1] + grid[i][j])分别对应右移和下移
        // 所以最后返回的值是 dp[m - 1][n - 1]
        int[][] dp = new int[m][n];
        
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(i == 0 && j == 0){
                    dp[0][0] = grid[0][0];
                }
                else if(i == 0 && j > 0){
                    dp[i][j] = dp[i][j - 1] + grid[i][j];
                }
                else if(i > 0 && j == 0){
                    dp[i][j] = dp[i - 1][j] + grid[i][j];
                }
                else{
                    dp[i][j] = Math.max(
                        dp[i - 1][j] + grid[i][j],
                        dp[i][j - 1] + grid[i][j]
                    );
                }
                
            }
        }
        return dp[m - 1][n - 1];

    }
}

Leecode——2021.04.17

标签:需要   翻转单词顺序   most   stringbu   获得   处理   else   delete   null   

原文地址:https://www.cnblogs.com/jiahaodaicoder/p/14669641.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!