LeetCode.S1.两数之和

LeetCode.S1

题目:

在这里插入图片描述

题目大意:

给定一个数组nums和一个目标值target,输出满足条件(两个数相加等于target)的这两个数的下标,两个数下标不能一样。

PS::该题中一定存在这两个数。

数据范围:

如图所示

一 、笨比解法 :

思路:

将nums数组变成pairs数组(pair<val, pos>,val:值,pos:下标),对pairs数组按照val升序排序(O(nlogn)),遍历pairs数组,当遍历到pairs[i]时,使用二分在pairs数组中查找值为target-pairs[i].val 的pairs[j], 如果pairs[i]的pairs[j]没找到,则往下一个继续找,如果找到了pairs[j]则分情况讨论:

  1. 如果找到的pairs[j]的坐标pairs[j].pos不等于pairs[i]的坐标pairs[i].pos,符合条件返回[-1, 1]。
  2. 如果找到的pairs[j]的坐标pairs[j].pos等于pairs[i]的坐标pairs[i].pos,说明找到的是同一个位置上的数,不符合条件,接下来,因为找到的是多个pairs[j].val中最左边的(如果存在多个相同的pairs[j].val话),所以看pairs[j+1].val是否为pairs[j].val,如果不是则说明只存在一个pairs[j].val,则不符合条件,返回[-1,1](再往下找无意义了,比如c的两个因子a,b,找a找b是一样的,a找过了,则b就不用找了)。如果是则说明有多个pairs[j].val,返回[i, j + 1],避免了i = j的情况。

PS:规定如果不存在返回[-1, -1],

代码:

import java.util.Arrays;

class Solution {
    public pair[] pairs;

    public class pair implements Comparable<pair>{
        int a, b;

        public pair(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int compareTo(pair o) {
            if (a < o.a)
                return -1;
            else if (a > o.a)
                return 1;
            else
                return 0;
        }
    }

    public int findX(pair[] nums, int x){

        int l = 0, r = nums.length - 1;
        while (l < r){
            int mid = l + r >> 1;
            if (nums[mid].a >= x) r = mid;
            else l = mid + 1;
        }
        if (nums[l].a == x)
            return l;
        else
            return -1;
    }

    public int[] twoSum(int[] nums, int target) {
        pairs = new pair[nums.length];
        for (int i = 0; i < nums.length; i ++ ){
            pairs[i] = new pair(nums[i], i);
        }
        Arrays.sort(pairs, 0, pairs.length);
        for (int i = 0; i < pairs.length; i ++ ){
            //如果有多个j,返回最左边的j
            int j = findX(pairs, target - pairs[i].a);
            //找到最左边的
            if (j != -1)
            {
                if (pairs[i].b == pairs[j].b){
                    if (j + 1 < pairs.length && pairs[i].a == pairs[j].a)
                        return new int[]{pairs[i].b, pairs[j + 1].b};
                    else
                        return new int[]{-1, -1};
                }else{
                    return new int[]{pairs[i].b, pairs[j].b};
                }
            }

        }
        return new int[]{-1, -1};
    }
}

public class Main {

    public static void main(String[] args) {
        int target = 3;
        int[] nums = new int[]{1, 3, 2};
        Solution solution = new Solution();
        System.out.println(Arrays.toString(solution.twoSum(nums, target)));
    }

}

时空复杂度分析等:

  • 时间复杂度 : O(nlogn)
  • 空间复杂度 : O(n)

二 、解法 :

思路:

使用HashMap,将查找的时间复杂度从O(logn)降为O(1),在遍历nums数组时,先查看hashmap<val, pos>的key中有无nums[i]所对应的target-nums[i],如果有,返回{hashMap.get(target - nums[i]), i},如果没有,则将(nums[i], i)加入hashMap中。

最后如果没找到则返回{-1,-1}。

代码:

class Solution{
    public int[] twoSum(int[] nums, int target){
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < nums.length; i ++ ){
            if (hashMap.containsKey(target - nums[i])){
                return new int[]{hashMap.get(target - nums[i]), i};
            }else{
                hashMap.put(nums[i], i);
            }
        }
        return new int[]{-1, -1};
    }
}


public class Main {

    public static void main(String[] args) {
        int target = 6;
        int[] nums = new int[]{1, 3, 3};
        Solution solution = new Solution();
        System.out.println(Arrays.toString(solution.twoSum(nums, target)));
    }

时空复杂度分析等:

  • 时间复杂度 : O(n)
  • 空间复杂度 : O(n)

附:

HashMap 遍历 以及神奇操作

Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
for (Map.Entry<Integer, Integer> entry : entries){
	System.out.println(entry.getKey() + ", " + entry.getValue());
 	entry.setValue(-1);
}

System.out.println("!!!");

Set<Map.Entry<Integer, Integer>> entries1 = hashMap.entrySet();
for (Map.Entry<Integer, Integer> entry : entries1){
	System.out.println(entry.getKey() + ", " + entry.getValue());
}

/*
1, 0
3, 1
4, 3
!!!
1, -1
3, -1
4, -1
*/

题目链接:

1. 两数之和 - 力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值