数据结构与算法--006 和为s的两个数字(easy)

地址:剑指Offer57.和为s的两个数字

方法一(暴力解法):

算法思路:

两层 for 循环列出所有两个数字的组合,判断是否等于目标值。

算法流程: 两层 for 循环:
  • 外层 for 循环依次枚举第一个数 a
  • 内层 for 循环依次枚举第二个数 b,让它与 a 匹配;ps: 这里有个魔鬼细节:我们挑选第二个数的时候,可以不从第一个数开始选,因为 a 前面的数我们都已经在之前考虑过了;因此,我们可以从 a 往后的数开始列举。
  • 然后将挑选的两个数相加,判断是否符合目标值。
java 复制代码
import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<Integer> twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (nums[i] + nums[j] == target) {
                    List<Integer> result = new ArrayList<>();
                    result.add(nums[i]);
                    result.add(nums[j]);
                    return result;
                }
            }
        }
        // 若未找到,返回 {-1, -1}
        List<Integer> notFound = new ArrayList<>();
        notFound.add(-1);
        notFound.add(-1);
        return notFound;
    }
}

解法二(双指针 - 对撞指针):

算法思路:

注意到本题是升序的数组,因此可以用「对撞指针」优化时间复杂度。

算法流程(附带算法分析,为什么可以使用对撞指针):

a. 初始化 leftright 分别指向数组的左右两端(这里不是我们理解的指针,而是数组的下标)b. 当 left < right 的时候,一直循环i. 当 nums[left] + nums[right] == target 时,说明找到结果,记录结果,并且返回;ii. 当 nums[left] + nums[right] < target 时:

  • 对于 nums[left] 而言,此时 nums[right] 相当于是 nums[left] 能碰到的最大值(别忘了,这里是升序数组哈~)。如果此时不符合要求,说明在这个数组里面,没有别的数符合 nums[left] 的要求了(最大的数都满足不了你,你已经没救了)。因此,我们可以大胆舍去这个数,让 left++,去比较下一组数据;
  • 那对于 nums[right] 而言,由于此时两数之和是小于目标值的,nums[right] 还可以选择比 nums[left] 大的值继续努力达到目标值,因此 right 指针我们按兵不动;iii. 当 nums[left] + nums[right] > target 时,同理我们可以舍去 nums[right](最小的数都满足不了你,你也没救了)。让 right--,继续比较下一组数据,而 left 指针不变(因为他还是可以去匹配比 nums[right] 更小的数的)。
java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        // a. 初始化left指向数组左端,right指向数组右端
        int left = 0;
        int right = nums.length - 1;
        
        // b. 当left < right时循环
        while (left < right) {
            int sum = nums[left] + nums[right];
            if (sum == target) {
                // i. 找到目标,返回结果
                return new int[]{left, right};
            } else if (sum < target) {
                // ii. 和小于目标,舍去当前left,left右移
                left++;
            } else {
                // iii. 和大于目标,舍去当前right,right左移
                right--;
            }
        }
        // 若未找到,返回-1(根据题目要求调整)
        return new int[]{-1, -1};
    }
}
相关推荐
大傻^2 分钟前
Spring AI Alibaba 可观测性实践:AI应用监控与链路追踪
java·人工智能·后端·spring·springaialibaba
云烟成雨TD7 分钟前
Spring AI Alibaba 1.x 系列【1】阿里巴巴 AI 生态
java·人工智能·spring
佑白雪乐9 分钟前
LCR 175. 计算二叉树的深度
算法·深度优先
诗人不写诗10 分钟前
spring是如何组织切面的
java·后端·spring
阿Y加油吧16 分钟前
力扣打卡day07——最大子数组和、合并区间
算法
想吃火锅100520 分钟前
【leetcode】105. 从前序与中序遍历序列构造二叉树
算法·leetcode·职场和发展
2401_8318249627 分钟前
嵌入式C++驱动开发
开发语言·c++·算法
靠沿29 分钟前
【优选算法】专题十八——BFS解决拓扑排序问题
算法·宽度优先
cui_ruicheng32 分钟前
C++数据结构进阶:哈希表实现
数据结构·c++·算法·哈希算法·散列表
光电笑映35 分钟前
高阶数据结构之红黑树详解
数据结构