算法快与慢--哈希+双指针

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

目前大概能写简单或者中等题了,正在追求优解


一、哈希

hash的原理在多线程里有讲,表面是一个连续的数组,在碰到hash冲突的时候会退为链表和红黑树,当一个链表上挂的东西过长的时候就会扩容,hash的初始化和扩容容量和他的概率有关,大概就是每个链表上挂8个的概率很小,所以以这个理由扩容。

hash在leetcode中主要表现为查找,因为一个东西hash后到List中去找到的时间复杂度是O(1),没有链表时就是比较hash值直接查找,有链表时会从头一个个比值,总的来说还是O(1),根据这个原理我认为hash是便于查找,不便于大量数据插入。

题目的范式是hash.containsKey(key)

不理解hash查找之前

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int i=0;
        int[] arr=new int[2];
        while( i <=nums.length-1){
        int temp=target-nums[i];
        for(int j=i+1;j<=nums.length-1;j++){
            if(nums[j]==temp){
                arr[0]=i;
                arr[1]=j;
                return arr;
            }
        }
        i++;
    }
    return arr;
}
}

想法基本没有问题,hash之后

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> hash=new HashMap<Integer,Integer>();
        for(int i=0;i<nums.length;i++){
        if(!hash.containsKey(target-nums[i])){
            hash.put(nums[i],i);
        }else{
            return new int[]{hash.get(target-nums[i]),i};
        }
        }
        return new int[0];
    }
}

这里外层是一次循环O(n),内层是hashO(1),相乘还是O(n),差距很大了

这题在ai帮助下想到了序列化key,然后hash,然后有点追求速度的想法。慢的原因是用了StringBuffer,这个有锁所以慢,后来用了StringBuilder就快一些。还有一种方法是排序,但是排序可能没有字母表好。

java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List finallist=new ArrayList();
        Map<String,List<String>> hash=new HashMap();
        for(String word:strs){
            int[] wordchar=new int[26];
            for(int i=0;i<word.length();i++){
            wordchar[word.charAt(i)-'a']++;
            }
            StringBuffer buffer=new StringBuffer();
            for(int i=0;i<26;i++){
            buffer.append(wordchar[i]).append(',');
            }
            if(!hash.containsKey(buffer.toString())){
                hash.put(buffer.toString(),new ArrayList<String>());
            }
            hash.get(buffer.toString()).add(word);
        }
        finallist.addAll(hash.values());
        return finallist;
    }
}
java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> finallist=new ArrayList<>();
        Map<String,List<String>> hash=new HashMap<>();
        for(String word:strs){
            int[] wordchar=new int[26];
            for(int i=0;i<word.length();i++){
            wordchar[word.charAt(i)-'a']++;
            }
            StringBuilder buffer=new StringBuilder();
            for(int i=0;i<26;i++){
            buffer.append(wordchar[i]).append(',');
            }
            if(!hash.containsKey(buffer.toString())){
                hash.put(buffer.toString(),new ArrayList<String>());
            }
            hash.get(buffer.toString()).add(word);
        }
        finallist.addAll(hash.values());
        return finallist;
    }
}

这题看了答案,不能有n-1.然后了解到for循环一直没有进去就不算时间复杂度.。除了提前返回,没有任何优化。

java 复制代码
class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> hash=new HashSet<Integer>();
        for(int n: nums){
            hash.add(n);
        }
        int max=0;

        for(int n:nums){
            if(!hash.contains(n-1)){
                int cur=1;
                while(hash.contains(n+1)){
                    cur++;
                    n++;
                }
                if(cur>nums.length/2){
                    return cur;
                }
                max=Math.max(max,cur);
            }
        }
        return max;
    }
}

二、双指针(未完)

这题想到了多次挪零,也普及了三种双指针:普通、快慢、滑窗。看到考的是双指针,就理所应当想到了将零与末尾元素交换,但是这样又无序了,有点矛盾,只能一个个挪0.

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int l=0,r=0;
        for(;r<nums.length;r++){
            if(nums[r]!=0){
                swap(nums,l,r);
                l++;
            }
        }
    }
    public void swap(int[] nums,int l,int r){
        int tmp;
        tmp=nums[l];
        nums[l]=nums[r];
        nums[r]=tmp;
    } 
}

了解到下标就是减现有0的个数,但是并没有更快

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int n,count=0;

        if(nums.length==1){
            return;
        }

        for(int i=0;i<nums.length;i++){
            if(nums[i]!=0 && count==0){
                continue;
            }
            if(nums[i]!=0 ){
                nums[i-count]=nums[i];
                nums[i]=0;
            }else{
                count++;
            }
            
        }
    }
}

方法没问题,问题在于非零元素的两次赋值,既要挪零,又要将非零元素置零

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int cur = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] != 0) {
            nums[cur] = nums[i];
            cur++;
        }
    }
    for (int i = cur; i < nums.length; i++) {
        nums[i] = 0;
    }
    }
}

虽然没有做出来,但是整体结构已经很像了,主要是数学功底不足,证明不出

java 复制代码
class Solution {
    public int maxArea(int[] height) {
        int l=0,r=height.length-1;
        int tmp=culculate(height,l,r);
        while(l<r){
            if(l+1<height.length-1 && culculate(height,l,r)<=culculate(height,l+1,r)){
                tmp=Math.max(culculate(height,l+1,r),tmp);
            }
            if(r-1>=0 && culculate(height,l,r)<=culculate(height,l,r-1)){
                tmp=Math.max(culculate(height,l,r-1),tmp);
                r--;
            }
            l++;
        }
        return tmp;
    }

    public int culculate(int[] height,int l,int r){
        int x=r-l;
        int ich=Math.min(height[l],height[r]);
        return x*ich;
    }
}
-----------------------------------------------------------------正解
public class Solution {
    public int maxArea(int[] height) {
        int l = 0, r = height.length - 1;
        int ans = 0;
        while (l < r) {
            int area = Math.min(height[l], height[r]) * (r - l);
            ans = Math.max(ans, area);
            if (height[l] <= height[r]) {
                ++l;
            }
            else {
                --r;
            }
        }
        return ans;
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/container-with-most-water/solutions/207215/sheng-zui-duo-shui-de-rong-qi-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、写这个的原因

也许对教学以

及初学者有帮助


总结

从最后一次代码来看,我目前的水平还处于if-else的水平,改错方法属于增加if-else限制来补充逻辑不够。匿名函数和新特性都不会,这是需要加强的地方。

相关推荐
Dillon Dong10 分钟前
【风电控制】TI TMS320F28379D 双CPU架构解析与任务分布设计
嵌入式硬件·算法·变流器·风电控制
小羊在睡觉6 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary6 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记6 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_468466856 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
sheeta19986 小时前
LeetCode 每日一题笔记 日期:2026.05.29 题目:3300. 最小元素
笔记·leetcode
_日拱一卒6 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
珂朵莉MM7 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法
Omics Pro8 小时前
首个!外源天然产物综合性代谢图谱
数据库·人工智能·算法·机器学习·r语言
voidmort8 小时前
3. 微调(Fine-tuning)与强化学习(RL)的核心思想
python·深度学习·算法