01数组算法/代码随想录

一、数组

好久没写算法题,之前喜欢按着习惯选择刷题,很早以前就听说代码随想录,今天跟着代码随想录再过一遍算法

1.1二分查找
  1. 常见疑问

    • middle一定是在[left, right]这个范围内
    • 标准代码不会越界,因为在else if中出现越界后,下一次循环就不会通过
  2. 左闭右闭区间

    • 代码示例

      public class BinarySearch<T> {public int BinarySearch(int[] arr, int target) {int left = 0, right = arr.length - 1, middle = 0;while (left <= right) {middle = (left + right) / 2;if (arr[middle] == target) {return middle;}else if(arr[middle] > target) {right = middle - 1;}else if(arr[middle] < target) {left = middle + 1;}}return -1;}public static void main(String[] args) {BinarySearch<Integer> binarySearch = new BinarySearch<>();int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};System.out.println(binarySearch.BinarySearch(arr, 5));}
      }
      
    1. 为什么是left <= right,举一个极端例子[2, 2],这个时候如果是没有=,则无法返回值

    2. 为什么是middle - 1 middle + 1,因为在arr[middle] > targetarr[middle] < target的时候,已经判断过arr

      [middle]已不在范围内了,直接排除即可

  3. 左闭右开区间

    • 代码示例

      public class BinarySearch<T> {public int BinarySearch(int[] arr, int target) {int left = 0, right = arr.length - 1, middle = 0;while (left < right) {middle = (left + right) / 2;if (arr[middle] == target) {return middle;}else if(arr[middle] > target) {right = middle;}else if(arr[middle] < target) {left = middle + 1;}}return -1;}public static void main(String[] args) {BinarySearch<Integer> binarySearch = new BinarySearch<>();int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};System.out.println(binarySearch.BinarySearch(arr, 5));}
      }
      
    1. 为什么是left < right,因为在极端情况下,比如不断缩减或一开始数组就是这样[2, 2),这明显错误,所以不存在相等
    2. 为什么是middle,因为是开区间,开区间本身就不包括在内
    3. 左开右闭同理,不赘诉
1.2双指针
1.2.1 快慢指针:拥有快慢指针,快指针先行,慢指针跟随条件移动
  1. 常用来数组元素的删除

    • 代码示例

      public int removeElement(int[] nums, int val) {int fast = 0, slow = 0;for (; fast < nums.length; ++fast) {if (nums[fast] != val) {nums[slow] = nums[fast];slow++;}}return slow;
      }
      
    • 实战

      1. 力扣27

        在这里插入图片描述

        暴力

        class Solution {public int removeElement(int[] nums, int val) {int n = nums.length;for(int i = 0; i < n; ++i) {if (nums[i] == val) {for (int j = i; j < n - 1; ++j) {nums[j] = nums[j + 1];}n -= 1;i -= 1;}}return n;}
        }
        

        快慢指针

        class Solution {public int removeElement(int[] nums, int val) {int n = nums.length;int fast = 0; int slow = 0;while (fast < n) {if (nums[fast] != val) {nums[slow] = nums[fast];slow++;}fast++;}return slow;}
        }
        
      • 在只有一个要移除的元素时和暴力的区别不大,只有在多个需要去除的元素才能体现出优势,但这里算是初步体现了快慢双指针的思想,让一个快指针去遍历每一个元素并判断每一个元素是否等于要删除的元素,慢指针代表索引号,这样避免了找到一次元素就要遍历一次的尴尬处境。这里体现了双指针思想,拥有两个自由的判断点,通过两种指针的交替配合从而避免暴力双层循环(暴力往往只有一个自由的判断点,外层循环的遍历),下面几题变种也体现了这种思想。
1.2.2 左右指针:两个指针相互操作,知道相撞
  1. 常用来比较大小并排序,实现O(n)时间复杂度

    • 代码示例

      public int[] sortedSquares(int[] nums) {int left = 0;int n = nums.length;int right = n - 1;int[] res = new int[n];while (right >= left) {if (nums[left] * nums[left] > nums[right] * nums[right]) {res[n - 1] = nums[left] * nums[left++];} else {res[n - 1] = nums[right] * nums[right--];}n -= 1;}return res;
      }
      
    • 这里为什么是right >= left和二分查找类似,因为都是左闭右闭的场景

    • 实战

      1. 力扣977

        在这里插入图片描述

        public int[] sortedSquares(int[] nums) {int left = 0;int n = nums.length;int right = n - 1;int[] res = new int[n];while (right >= left) {if (nums[left] * nums[left] > nums[right] * nums[right]) {res[n - 1] = nums[left] * nums[left++];} else {res[n - 1] = nums[right] * nums[right--];}n -= 1;}return res;
        }
        
      • 左指针和右指针都往中间靠,如果右指针比左指针大,则右指针–,如果左指针比右指针大,则左指针++,知道右指针小于左指针
1.2.3 滑动窗口
  1. 用来计算哪一段区间最符合要求

    • 实战

      1. 力扣209

        在这里插入图片描述

        暴力(失败,超出时间限制)

        class Solution {public int minSubArrayLen(int target, int[] nums) {int res = Integer.MAX_VALUE;int n = nums.length - 1;for (int i = 0; i <= n; ++i) {int add = 0;for (int j = i; j <= n; ++j) {add += nums[j];if (add >= target) {res = Math.min(j - i + 1, res);break;}}}return res == Integer.MAX_VALUE ? 0 : res;}
        }
        

        滑动窗口

        public int minSubArrayLen(int target, int[] nums) {
        int left = 0, right = 0;
        int n = nums.length;
        int result = Integer.MAX_VALUE;
        int subLength = 0;
        int sum = 0;
        for (; right < n; ++right) {sum += nums[right];while (sum >= target) {subLength = right - left + 1;result = Math.min(subLength, result);sum -= nums[left++];}
        }
        return result == Integer.MAX_VALUE ? 0 : result;
        }
        
    • 若使用头指针,则和暴力没什么区别,所以选择尾部。滑动窗口一层循环则可直接计算,尾指针先移动,满足条件时,尾指针不动,头指针+1,再判断,如果通过,则更新result。否则继续移动尾指针,直到尾指针到数组尾部结束。

1.3模拟
  1. 对于难以应用算法的问题,可以通过模拟问题中的思路进行代码编写

    • 实战

    • 力扣54

      在这里插入图片描述

      class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> res = new ArrayList<Integer>();int u = 0; int d = matrix.length - 1; int l = 0;int r = matrix[0].length - 1;while(true) {for (int i = l; i <= r; ++i) {res.add(matrix[u][i]);}if (++u > d) break;for (int i = u; i <= d; ++i) {res.add(matrix[i][r]);}if (--r < l) break;for (int i = r; i >= l; --i) {res.add(matrix[d][i]);}if (--d < u) break;for (int i = d; i >= u; --i) {res.add(matrix[i][l]);}if (++l > r) break;}return res;}
      }
      
    • 这是很常见的模拟之一,与力扣59互补,拿到这种题有常见的思路

      1. 大多数这种题目,都是给予条件,根据条件进行不断的计算。所以我们需要确定 1.循环中的计算 2.循环条件 3.终止条件

        • 上述写法是比较快的,有些地方是较优解的

          • 我比较喜欢使用while循环,因为while循环往往可以表示确定次数的循环和不确定次数的循环,for循环是确定次数的。但for循环也有一些优势,简洁明了,很容易判断循环条件

          • 拿与力扣59举例,那题是一个正方形,所以只会出现一种特殊情况就是层数为奇数的时候,需要手动添加垂直水平中间数组中的值,而这里行列是不一样的,所以终止的情况有多种,上下左右都有可能,所以直接在while循环中添加判断是比较复杂的

          • 这里,我再说个结论,中间的循环写法很大程度依靠终止条件的写法。力扣59强调每一个方向使用相同开闭区间的数组。这里是每一个变都是闭区间,是因为59题是依靠着一个实时的变量来控制数字在数组中的走向,这里判断条件不好写绕圈次数,因为上面说过终止条件判断较多,所以不太好靠一个实时变量来控制走向。由于终止条件很多,所以这里引用上下左右边界,就很好的解决了循环内写法的问题

          • 这种模拟的方法效率更高,大家在写模拟的时候,可以先将思路列举好,起始条件、终止条件、遍历写法,然后再一步一步优化

  • 总结

    1. 双指针技术的魅力就在于它通过一个主循环来控制遍历,同时在循环内进行值的计算和条件判断,从而避免了不必要的嵌套循环。这种方式不仅提高了效率,还使得代码更加简洁和易于理解。所以写双指针的时候需要在一层循环就进行计算,

      • 以下的写法就是为了写双指针而写,实际上就是暴力,没有做到第一层循环就计算,力扣209

        public int minSubArrayLen(int target, int[] nums) {int start = 0, end = 0;int n = nums.length;int res = Integer.MAX_VALUE;while (end < n) {int add = 0;int i = start;// 计算窗口内的和for (; i <= end; i++) {add += nums[i];if (add >= target) {res = Math.min(end - start + 1, res);break;  // 找到满足条件的和后,退出循环}}// 如果找到满足条件的和,移动 startif (add >= target) {start++;} else {end++;  // 否则,移动 end}}return res == Integer.MAX_VALUE ? 0 : res;  // 如果没有找到,返回 0
        }
        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/449991.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【windows个性化】在 Windows 10/11 上使 Windows 任务栏半透明/透明

实现目的&#xff1a;在 Windows 10/11 上使 Windows 任务栏半透明/透明. TranslucentTB plugin 描述 只需几 MB 内存&#xff0c;几乎不占用 CPU&#xff0c;便可以在 Windows 10/11 上使 Windows 任务栏半透明/透明的轻量小工具 功能 高级颜色选择器(color picker)&…

X(twitter)推特广告类型有哪些?如何选择?

X&#xff08;twitter&#xff09;推特是全球最热门的几大社交媒体平台之一&#xff0c;也是很多电商卖家进行宣传推广工作的阵地之一。在营销过程中不可避免地需要借助平台广告&#xff0c;因此了解其广告类型和适配场景也十分重要。 一、广告类型及选择 1.轮播广告 可滑动的…

JavaScript的100个概念

JavaScript对初学者来说既是福音&#xff0c;也是挑战。一方面&#xff0c;掌握它后可以构建各种项目&#xff0c;比如网站、应用程序和服务器&#xff0c;还能在很多行业找到工作。但另一方面&#xff0c;它又充满怪异之处&#xff0c;并被各种复杂的库和框架包围。在这段课程…

FLUX LoRA模型揭秘:COMFYUI中的AI绘画新动力!

嗨&#xff0c;艺术爱好者们&#xff01;今天我们要揭开一个神秘的面纱——FLUX LoRA模型&#xff0c;这个模型就像是一个神奇的魔法师&#xff0c;将COMFYUI中的AI绘画提升到了一个新的高度&#xff01; 想象一下&#xff0c;你有一个AI助手&#xff0c;它能够理解你的绘画梦…

【Redis】Zset类型常用命令

文章目录 一. Zset有序集合简介.二. 添加元素相关命令.2.1 向有序集合中添加元素(zadd) 三. 查询元素相关操作.3.1 查询有序集合中的元素个数( zcard zcount)3.2 查询指定区间内的元素(zrange zrevrange zrangebyscore)3.3 查询有序集合中指定成员的排名(zrank zrevrank )3.4 查…

钴粉Co纳米微球100nm|CoNP/CoN2-C催化剂

钴粉Co纳米微球100nm|CoNP/CoN2-C催化剂 钴粉Co纳米微球100nm是一种具有独特物理和化学性质的纳米材料&#xff0c;因其高比表面积、优良的磁性和化学稳定性&#xff0c;在多个领域展现出广阔的应用前景。以下是关于钴粉Co纳米微球100nm的相关信息&#xff1a; 性质 高比表面…

ubuntu20.04安装gerrit

1、update 2、updategrale 一&#xff1a;安装前准备 配置管理gerrit的专属账号&#xff1a;(本次测试安装我用的ROOT) sudo adduser gerrit sudo usermod -a -G sudo gerrit //分配sudo 权限 sudo su gerrit java、git环境&#xff1a; sudo apt-get update sudo apt-g…

群晖前面加了雷池WAF,安装失败,然后无法识别出用户真实访问IP

有nas的相信对公网都不模式&#xff0c;在现在基础上传带宽能有100兆的时代&#xff0c;有公网代表着家里有一个小服务器&#xff0c;像百度网盘&#xff0c;优酷这种在线服务都能部署为私有化服务。但现在运营商几乎不可能提供公网ip&#xff0c;要么自己买个云服务器做内网穿…

多jdk版本环境下,jenkins系统设置需指定JAVA_HOME环境变量

一、背景 由于不同项目对jdk版本的要求不同&#xff0c;有些是要求jdk11&#xff0c;有些只需要jdk8即可。 而linux机器上安装jdk的方式又多种多样&#xff0c;最后导致jenkins打包到底使用的是哪个jdk&#xff0c;比较混乱。 1、java在哪 > whereis java java: /usr/bin/…

测试人生 | 双非院校,2年工作经验年薪近20万

本人本科毕业于双非院校&#xff0c;大学毕业之后就开始从事软件测试工作&#xff0c;有两年多的工作经验&#xff0c;工作当中学习的测试技能较少&#xff0c;比较多重复的工作内容&#xff0c;主要对软件进行功能测试、简单的接口测试及专项测试&#xff0c;自学的测试知识零…

【STL】模拟实现list

目录 list需要实现的接口 结点类的创建 迭代器类的实现 构造函数 运算符的重载 --运算符的重载 !运算符重载和运算符重载 operator* operator-> list的模拟实现 构造函数 拷贝构造函数 赋值运算符重载函数 析构函数 迭代器相关函数 begin和end front和back …

【超详细】TCP协议

TCP(Transmission Control Protocol 传输控制协议) 传输层协议有连接可靠传输面向字节流 为什么TCP是传输控制协议呢&#xff1f; 我们以前所看到的write接口&#xff0c;都是把用户级缓冲区的数据拷贝到发送缓冲区中&#xff0c;然后数据就由TCP自主决定了&#xff0c;所以…

crashrpt3 开源项目的Vs 2022 C++20及其以上的编译

1. 首先从github 下载源代码 crashrpt3 2. 用CMake Gui 编译成vs studio 工程文件 2.1 点击 config 按钮 2.2 依次点击 Generate 按钮、Open Project 按钮.之后vs 2022 会打开编译好的sln工程文件 3.全选解决方案里面的所有项目,设置C语言标准,我这里设置是最新C,即启用的是…

【文档智能】文本文字识别、公式识别、表格文字识别核心算法及思路及实践-DBNet、CRNN、TrOCR

前言 OCR技术作为文档智能解析链路中的核心组件之一&#xff0c;贯穿整个技术链路&#xff0c;包括&#xff1a;文字识别、表格文字识别、公式识别&#xff0c;参看下面这张架构图&#xff1a; 前期介绍了很多关于文档智能解析相关核心技术及思路&#xff0c;本着连载的目的&a…

IT监控平台可视化:多维度展示助力运维效率提升

在信息化时代&#xff0c;IT设备的稳定性与业务的连续性紧密相连&#xff0c;任何细微的故障都可能给企业带来巨大的损失。因此&#xff0c;IT运维团队面临着前所未有的挑战&#xff0c;他们需要迅速、准确地识别和解决问题&#xff0c;以确保业务的平稳运行。而IT监控平台的可…

应届生毕业找不到工作转行IT需要做好哪些准备呢?

前言 相信这是很多即将毕业的应届生们都非常关心的问题。在这里&#xff0c;我们将站在一个应届生毕业且对IT行业感兴趣的角度&#xff0c;来探讨一下这个问题。 首先&#xff0c;我们先来了解一下什么是应届生。应届生是指在学校毕业之后&#xff0c;能够在当年或者下一年度…

AIGC验证码如何对抗,AIGC VS AIGC

AI类型的验证码&#xff0c;当然使用AI对对抗&#xff0c;使用大量的样本叠加训练&#xff0c;我的生成如下: 如果可以生词大量词汇&#xff0c;那么准确率必然上升&#xff0c;有办法的可以讨论

大模型系列:RAG技术深度解析

文末有福利&#xff01; RAG 是2023年最流行的基于 LLM 的应用系统架构。有许多产品几乎完全建立在 RAG 之上&#xff0c;覆盖了结合网络搜索引擎和 LLM 的问答服务&#xff0c;到成千上万个数据聊天的应用程序。很多人将RAG和Agent 作为大模型应用的两种主流架构&#xff0c;…

CTFHUB技能树之HTTP协议——响应包源代码

开启靶场&#xff0c;打开链接&#xff1a; 是个贪吃蛇小游戏&#xff0c;看不出来有什么特别的地方 用burp抓包看看情况&#xff1a; 嗯&#xff1f;点击“开始”没有抓取到报文&#xff0c;先看看网页源代码是什么情况 居然直接给出flag了&#xff0c;不知道这题的意义何在 …

pip离线下载和安装第三方库

pip离线下载和安装第三方库 离线下载离线安装 离线下载 下载依赖库&#xff08;.whl文件&#xff09;&#xff0c;比如下载polars库&#xff0c;并指定重清华源下载&#xff0c;会自动下载依赖的库&#xff0c;并保存到当前目录中&#xff0c;下载命令如下&#xff1a; # 下载…