Leetcode第一题_Two Sum

本文详细解析LeetCode算法题TwoSum,从原始思路到优化算法,包括使用哈希表和归并排序解决该问题。文章还讨论了算法的时间复杂度优化和特殊情况处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode算法题第一题Two Sum,题目如下

Two Sum Total Accepted: 86454 Total Submissions: 490141 My Submissions Question Solution
Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

这一题的大概意思,是说给你一个数组和一个数,从数组中找出两个数的和等于这一数,然后输出这两个数在数组中的位置,数组的下标从1开始。

看到这一题的第一个想法是,卧槽,这么简单,通过率才17%,我是不是进错网站了。然后啪啪啪的写出解法,写的过程中一看时间复杂度是O(n*n),我就知道肯定不对了。

//    public int[] twoSum(int[] numbers, int target) {
//      int [] result = new int [2];
//      for (int i = 0; i < numbers.length; i++) {
//          for (int j = i+1; j < numbers.length; j++) {
//              int sum = numbers[i]+numbers[j];
//              if (sum == target) {
//                   result[0] = i+1;
//                   result[1] = j+1;
//              }
//          }
//      }
//      return result;
//    }

心中冒出一个声音,能不能再给力一点!我想,这个肯定是要求时间复杂度为O(n*logn)的,那应该是先将数组排序弄成有序数组,然后分别从两端相加,如果小于目标值,左端下标右移,大于目标值,右端下标左移。嘴角不由露出微笑,这把一定行。

但数组的下标发生了改变,输出不是原下标了!这不是问题,来一个hashmap,用数组的值做key,原下标为value不就ok了?我去,什么鬼,还有相同的值,key重复了怎么办?嗯,开放地址发咯,给这个key加个100000,到时候在两数相等的时候处理一下就好了嘛。

于是又啪啪啪的整出个快排,弄出解法,submit,然后继续得到time limted。傻眼了,麻辣,这是为什么!定睛一看,原来给出的超时case是一个超长的,有序的数组,妈蛋,这不正好是快排的最差情况吗!

好吧,我归并。于是,终于ac了!

public static int[] twoSum(int[] numbers, int target) {
    int [] result = new int [2];
//      hashmap以数组值为key,原下标为value
    HashMap<Integer, Integer> map = new HashMap<Integer,Integer>(numbers.length,(float)0.75);
    for (int i = 0; i < numbers.length; i++) {
        Object k = map.put(numbers[i], i);
//          如果key值相等,则改变key值,存储原来的下标
        if (k!=null) {
            map.put(100000+numbers[i], (Integer)k);
        }
    }
//      数组排序
    mergesort(numbers);
    int sum = -1;
    int i = 0;
    int j = numbers.length-1;
    while (i<j) {

        sum = numbers[i]+numbers[j];
        if(sum<target)
            i++;
        if (sum>target)
            j--;
        if (sum == target) {
            if (numbers[i] == numbers[j]) {
                result[0] = map.get(numbers[i]+100000)+1;
                result[1] = map.get(numbers[j])+1;
            }
            else {
                result[0] = map.get(numbers[i])+1;
                result[1] = map.get(numbers[j])+1;
            }
            if (result[0]>result[1]) {
                int t = result[0];
                result[0] = result[1];
                result[1] = t;
            }
            break;
        }
    }
    return result;
}

//    归并排序算法
public static void merge(int[] r,int[] order,int t,int m,int k){
    int i = t;
    int s = t;
    int j = m+1;
    while (i<=m&&j<=k) {
        if (r[i]<r[j]) {
            order[s] = r[i];
            s++;
            i++;
        }
        else {
            order[s] = r[j];
            s++;
            j++;
        }
    }
    while (i<=m) {
        order[s] = r[i];
        s++;
        i++;
    }
    while (j<=k) {
        order[s] = r[j];
        s++;
        j++;
    }
}
public static void merges(int[] r,int [] order,int s){
    int p = 0;
    while(p+2*s-1<=r.length-1){
        merge(r, order, p, p+s-1,p+2*s-1);
        p = p+2*s;
    }
    if (p+s-1<r.length-1) {
        merge(r, order, p, p+s-1, r.length-1);
    }
    else {
        for (int i = p; i < order.length; i++) {
            order[i] = r[i];
        }
    } 
}
public static void mergesort(int[] r){
    int s = 1;
    int [] order = new int [r.length];
    while (s<r.length) {
        merges(r, order, s);
        s = 2*s;
        merges(order, r, s);
        s = 2*s;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值