当前位置: 首页 > news >正文

经典算法题总结:数组常用技巧(双指针,二分查找和位运算)篇

双指针

在处理数组和链表相关问题时,双指针技巧是经常用到的,双指针技巧主要分为两类:左右指针快慢指针。所谓左右指针,就是两个指针相向而行或者相背而行;而所谓快慢指针,就是两个指针同向而行,一快一慢。

15. 三数之和(⭐️⭐️)

思路

两数之和 -> 三数之和 -> N 数之和

代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class ThreeSumTarget {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> res = new ArrayList<>();Arrays.sort(nums);for (int i = 0; i < nums.length; i++) {if (nums[i] > 0) {return res;}if (i > 0 && nums[i] == nums[i - 1]) {continue;}int left = i + 1;int right = nums.length - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (sum < 0) {left++;} else if (sum > 0) {right--;} else {res.add(Arrays.asList(nums[i], nums[left], nums[right]));while ((left < right) && (nums[right] == nums[right - 1])) {right--;}while ((left < right) && nums[left] == nums[left + 1]) {left++;}right--;left++}}}return res;}}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class NSumTarget {public List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);return nSumTarget(nums, 3, 0, 0);}private List<List<Integer>> nSumTarget(int[] nums, int n, int start, int target) {int size = nums.length;List<List<Integer>> res = new ArrayList<>();if (n < 2 || size < n) {return res;}if (n == 2) {int low = start;int high = size - 1;while (low < high) {int sum = nums[low] + nums[high];int left = nums[low];int right = nums[high];if (sum < target) {while (low < high && nums[low] == left) {low++;}} else if (sum > target) {while (low < high && nums[high] == right) {high--;}} else {res.add(new ArrayList<>(Arrays.asList(left, right)));while (low < high && nums[low] == left) {low++;}while (low < high && nums[high] == right) {high--;}}}} else {for (int i = start; i < size; i++) {if (i > start && nums[i] == nums[i - 1]) {continue;}List<List<Integer>> sub = nSumTarget(nums, n - 1, i + 1, target - nums[i]);for (List<Integer> arr : sub) {arr.add(nums[i]);res.add(arr);}while (i < size - 1 && nums[i] == nums[i + 1]) {i++;}}}return res;}}

复杂度

  • 时间复杂度:O(N^2)
  • 空间复杂度:O(logN)

5. 最长回文子串

思路

寻找回文串的问题核心思想是:从中间开始向两边扩散来判断回文串,对于最长回文子串,就是这个意思:

for 0 <= i < len(s):找到以 s[i] 为中心的回文串更新答案

找回文串的关键技巧是传入两个指针 leftright 向两边扩散,因为这样实现可以同时处理回文串长度为奇数和偶数的情况。

for 0 <= i < len(s):# 找到以 s[i] 为中心的回文串palindrome(s, i, i)# 找到以 s[i] 和 s[i+1] 为中心的回文串palindrome(s, i, i + 1)更新答案

代码

public class LongestPalindromicSubstring {public String longestPalindrome(String s) {String res = "";for (int i = 0; i < s.length(); i++) {String s1 = palindrome(s, i, i); // 奇数情况String s2 = palindrome(s, i, i + 1); // 偶数情况res = res.length() > s1.length() ? res : s1;res = res.length() > s2.length() ? res : s2;}return res;}private String palindrome(String s, int left, int right) {while (left >= 0 && right < s.length()&& s.charAt(left) == s.charAt(right)) {left--;right++;}return s.substring(left + 1, right);}}

复杂度

  • 时间复杂度:O(N^2)
  • 空间复杂度:O(N)

88. 合并两个有序数组(⭐️⭐️)

思路

代码

public class MergeTwoArray {// 双指针public void merge1(int[] nums1, int m, int[] nums2, int n) {int p1 = 0;int p2 = 0;int[] sorted = new int[m + n];int cur = 0;int i = 0;while (p1 < m && p2 < n) {if (nums1[p1] < nums2[p2]) {sorted[i++] = nums1[p1++];} else {sorted[i++] = nums2[p2++];}}while (p1 < m) {sorted[i++] = nums1[p1++];}while (p2 < n) {sorted[i++] = nums2[p2++];}for (i = 0; i < m + n; i++) {nums1[i] = sorted[i];}}// 逆向双指针public void merge2(int[] nums1, int m, int[] nums2, int n) {int i = m - 1;int j = n - 1;int p = nums1.length - 1;while (i >= 0 && j >= 0) {if (nums1[i] > nums2[j]) {nums1[p] = nums1[i];i--;} else {nums1[p] = nums2[j];j--;}p--;}while ( j>= 0) {nums1[p] = nums2[j];j--;p--;}}}

复杂度

  • 时间复杂度:O(N)
  • 空间复杂度:双指针:O(N),逆向双指针:O(1)

二分查找

int binarySearch(int[] nums, int target) {int left = 0, right = nums.length - 1; while(left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1; } else if(nums[mid] == target) {// 直接返回return mid;}}// 直接返回return -1;
}

33. 搜索旋转排序数组(⭐️⭐️)

思路

代码

public class SearchInRotatedSortedArray {/*nums = [4,5,6,7,0,1,2]例如 target = 5, 目标值在左半段,因此在 [4, 5, 6, 7, inf, inf, inf] 这个有序数组里找就行了例如 target = 1, 目标值在右半段,因此在 [-inf, -inf, -inf, -inf, 0, 1, 2] 这个有序数组里找就行了*/public int search(int[] nums, int target) {int left = 0;int right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {return mid;}if (target >= nums[0]) {if (nums[mid] < nums[0]) {nums[mid] = Integer.MAX_VALUE;}} else {if (nums[mid] >= nums[0]) {nums[mid] = Integer.MIN_VALUE;}}if (nums[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;}}

复杂度

  • 时间复杂度:O(logN)
  • 空间复杂度:O(1)

69. x 的平方根(⭐️⭐️)

思路

代码

public class Sqrt {public int mySqrt(int x) {int left = 0, right = x, res = -1;while (left <= right) {int mid = left + (right - left) / 2;if ((long) mid * mid <= x) {res = mid;left = mid + 1;} else {right = mid - 1;}}return res;}}

复杂度

  • 时间复杂度:O(N)
  • 空间复杂度:O(1)

240. 搜索二维矩阵 II(⭐️)

思路

代码

public class SearchMatrix {public boolean searchMatrix(int[][] matrix, int target) {int m = matrix.length, n = matrix[0].length;int i = 0, j = n - 1;while (i < m && j >= 0) {if (matrix[i][j] == target) {return true;}if (matrix[i][j] < target) {i++; // 需要大一点,往下移动} else {j--; // 需要小一点,往左移动}}return false;}}

复杂度

  • 时间复杂度:O(M + N)
  • 空间复杂度:O(1)

34. 在排序数组中查找元素的第一个和最后一个位置(⭐️)

思路

代码

public class SearchRange {public int[] searchRange(int[] nums, int target) {return new int[]{leftRange(nums, target), rightRange(nums, target)};}private int leftRange(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;} else if (nums[mid] == target) {right = mid - 1;}}if (left < 0 || left >= nums.length) {return -1;}return nums[left] == target ? left : -1;}private int rightRange(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;} else if (nums[mid] == target) {left = mid + 1;}}if (right < 0 || right >= nums.length) {return -1;}return nums[right] == target ? right : -1;}}

复杂度

  • 时间复杂度:O(log(N))
  • 空间复杂度:O(1)

34. 在排序数组中查找元素的第一个和最后一个位置(⭐️)

思路

代码

class Solution {public int[] searchRange(int[] nums, int target) {return new int[]{leftBound(nums, target), rightBound(nums, target)};}private int leftBound(int[] nums, int target) {int left = 0, right = nums.length - 1;// 搜索区间为 [left, right]while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {// 搜索区间变为 [mid+1, right]left = mid + 1;} else if (nums[mid] > target) {// 搜索区间变为 [left, mid-1]right = mid - 1;} else if (nums[mid] == target) {// 收缩右侧边界right = mid - 1;}}// 检查出界情况if (left >= nums.length || nums[left] != target) {return -1;}return left;}private int rightBound(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;} else if (nums[mid] == target) {// 这里改成收缩左侧边界即可left = mid + 1;}}// 这里改为检查 right 越界的情况,见下图if (right < 0 || nums[right] != target) {return -1;}return right;}}

复杂度

  • 时间复杂度:O(log(N))
  • 空间复杂度:O(N)

162. 寻找峰值(⭐️)

思路

代码

public class FindPeakElement {public int findPeakElement(int[] nums) {int left = 0, right = nums.length - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] > nums[mid + 1]) {right = mid;} else {left = mid + 1;}}return left;}}

复杂度

  • 时间复杂度:O(logN)
  • 空间复杂度:O(1)

位运算

136. 只出现一次的数字(⭐️)

思路

代码

public class SingleNumber {public int singleNumber(int[] nums) {int res = 0;for (int n : nums) {res ^= n;}return res;}}

复杂度

  • 时间复杂度:O(N)
  • 空间复杂度:O(1)

相关文章:

经典算法题总结:数组常用技巧(双指针,二分查找和位运算)篇

双指针 在处理数组和链表相关问题时&#xff0c;双指针技巧是经常用到的&#xff0c;双指针技巧主要分为两类&#xff1a;左右指针和快慢指针。所谓左右指针&#xff0c;就是两个指针相向而行或者相背而行&#xff1b;而所谓快慢指针&#xff0c;就是两个指针同向而行&#xf…...

版本控制基础理论

一、本地版本控制 在本地记录文件每次的更新&#xff0c;可以对每个版本做一个快照&#xff0c;或是记录补丁文件&#xff0c;适合个人使用&#xff0c;如RCS. 二、集中式版本控制&#xff08;代表SVN&#xff09; 所有的版本数据都保存在服务器上&#xff0c;协同开发者从…...

微分方程(Blanchard Differential Equations 4th)中文版Section1.4

1.4 NUMERICAL TECHNIQUE: EULER’S METHOD 上一节中讨论的斜率场的几何概念与近似微分方程解的基本数值方法密切相关。给定一个初值问题 d y d t = f ( t , y ) , y ( t 0 ) = y 0 , \frac{dy}{dt}=f(t,y), \quad y(t_0) = y_0, dtdy​=f(t,y),y(t0​)=y0​, 我们可以通过首…...

求职Leetcode算法题(7)

1.搜索旋转排序数组 这道题要求时间复杂度为o&#xff08;log n&#xff09;&#xff0c;那么第一时间想到的就是二分法&#xff0c;二分法有个前提条件是在有序数组下&#xff0c;我们发现在这个数组中存在两部分是有序的&#xff0c;所以我们只需要对前半部分和后半部分分别…...

ActiveMQ、RabbitMQ、Kafka、RocketMQ在事务性消息、性能、高可用和容错、定时消息、负载均衡、刷盘策略的区别

ActiveMQ、RabbitMQ、Kafka、RocketMQ这四种消息队列在事务性消息、性能、高可用和容错、定时消息、负载均衡、刷盘策略等方面各有其特点和差异。以下是对这些方面的详细比较&#xff1a; 1. 事务性消息 ActiveMQ&#xff1a;支持事务性消息。ActiveMQ可以基于JMS&#xff08…...

HanLP分词的使用与注意事项

1 概述 HanLP是一个自然语言处理工具包&#xff0c;它提供的主要功能如下&#xff1a; 分词转化为拼音繁转简、简转繁提取关键词提取短语提取词语自动摘要依存文法分析 下面将介绍其分词功能的使用。 2 依赖 下面是依赖的jar包。 <dependency><groupId>com.ha…...

Python 的进程、线程、协程的区别和联系是什么?

一、区别 1. 进程 • 定义&#xff1a;进程是操作系统分配资源的基本单位。 • 资源独立性&#xff1a;每个进程都有独立的内存空间&#xff0c;包括代码、数据和运行时的环境。 • 并发性&#xff1a;可以同时运行多个进程&#xff0c;操作系统通过时间片轮转等方式在不同…...

实时数据推送:Spring Boot 中两种 SSE 实战方案

在 Web 开发中&#xff0c;实时数据交互变得越来越普遍。无论是股票价格的波动、比赛比分的更新&#xff0c;还是聊天消息的传递&#xff0c;都需要服务器能够及时地将数据推送给客户端。传统的 HTTP 请求-响应模式在处理这类需求时显得力不从心&#xff0c;而服务器推送事件&a…...

数据守护者:SQL一致性检查的艺术与实践

标题&#xff1a;数据守护者&#xff1a;SQL一致性检查的艺术与实践 在数据驱动的商业世界中&#xff0c;数据的一致性是确保决策准确性和业务流程顺畅的关键。SQL作为数据查询和操作的基石&#xff0c;提供了多种工具来维护数据的一致性。本文将深入探讨如何使用SQL进行数据一…...

jenkins配置+vue打包多环境切换

jenkins配置流水线过程 1.新建item 加入相关的参数就行了。 流水线脚本设置 后端脚本 node {stage checkoutsh"""#每次打包清空工作空间目录rm -rf $workspace/*cd $workspace#到工作空间下从远端svn服务端拉取代码svn co svn://10.1.19.21/repo/技术中台/低…...

idea和jdk的安装教程

1.JDK的安装 下载 进入官网&#xff0c;找到你需要的JDK版本 Java Downloads | Oracle 中国 我这里是windows的jdk17&#xff0c;选择以下 安装 点击下一步&#xff0c;安装完成 配置环境变量 打开查看高级系统设置 在系统变量中添加两个配置 一个变量名是 JAVA_HOME …...

HTML静态网页成品作业(HTML+CSS)——电影网首页网页设计制作(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…...

大数据系列之:Flink Doris Connector,实时同步数据到Doris数据库

大数据系列之&#xff1a;Flink Doris Connector&#xff0c;实时同步数据到Doris数据库 一、版本兼容性二、使用三、Flink SQL四、DataStream五、Lookup Join六、配置通用配置项接收器配置项查找Join配置项 七、Doris 和 Flink 列类型映射八、使用Flink CDC访问Doris的示例九、…...

LabVIEW VI 多语言动态加载与运行的实现

在多语言应用程序开发中&#xff0c;确保用户界面能够根据用户的语言偏好动态切换是一个关键需求。本文通过分析一个LabVIEW程序框图&#xff0c;详细说明了如何使用LabVIEW中的属性节点和调用节点来实现VI&#xff08;虚拟仪器&#xff09;界面语言的动态加载与运行。此程序允…...

Unity引擎基础知识

目录 Unity基础知识概要 1. 创建工程 2. 工程目录介绍 3. Unity界面和五大面板 4. 游戏物体创建与操作 5. 场景和层管理 6. 组件系统 7. 脚本语言C# 8. 物理引擎和UI系统 学习资源推荐 Unity引擎中如何优化大型游戏项目的性能&#xff1f; Unity C#脚本语言的高级编…...

练习题- 探索正则表达式对象和对象匹配

正则表达式(Regular Expressions)是一种强大而灵活的文本处理工具,它允许我们通过模式匹配来处理字符串。这在数据清理、文本分析等领域有着广泛的应用。在Python中,正则表达式通过re模块提供支持,学习和掌握正则表达式对于处理复杂的文本数据至关重要。 本文将探索如何在…...

Java集合提升

1. 手写ArrayList 1.1. ArrayList底层原理细节 底层结构是一个长度可以动态增长的数组&#xff08;顺序表&#xff09;transient Object[] elementData; 特点&#xff1a;在内存中分配连续的空间&#xff0c;只存储数据&#xff0c;不存储地址信息。位置就隐含着地址。优点 节…...

uniapp 微信小程序生成水印图片

效果 源码 <template><view style"overflow: hidden;"><camera device-position"back" flash"auto" class"camera"><cover-view class"text-white padding water-mark"><cover-view class"…...

ElasticSearch相关知识点

ElasticSearch中的倒排索引是如何工作的&#xff1f; 倒排索引是ElasticSearch中用于全文检索的一种数据结构&#xff0c;与正排索引不同的是&#xff0c;正排索引将文档按照词汇顺序组织。而倒排索引是将词汇映射到包含该词汇的文档中。 在ElasticSearch中&#xff0c;倒排索…...

css 文字图片居中及网格布局

以下内容纯自已个人理解&#xff0c;直接上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...