《程序员代码面试指南》TwoSum 问题——java实现

TwoSum问题

问题描述:

题目一:

给定一个数组arr,和一个整数aim,请返回哪两个位置的数可以加出aim来。 可以假设每个数组里只有一组答案。

示例1:

arr = {2, 7, 11, 15},aim= 9
返回{0,1},因为arr[0] + arr[1] = 2 + 7 = 9

题目思路:

思路一:
要找出哪两个位置的和等于aim,首先要对数组进行排序,并且还要记录排序之前每个元素的index,(本题采用堆排序的思想,时间复杂度较低)。然后设置两个指针分别指向头数组和尾数组。如果两指针所指的元素的和大于aim,则让右指针左移;如果两指针所指的元素的和小于aim,则让左指针右移;如果相等,则直接返回两指针元素所在的index,循环结束。
时间复杂度:o(nlogn)
空间复杂度:o(1)
思路二:
用哈希表来存储每次遍历到的key和value。若target-arr[i]的值已经在map中,则直接返回两坐标即可。
时间复杂度:o(n)
空间复杂度:o(n)

题目难度:

easy

代码实现:

思路一:

  public static int[] twoSum(int[] arr, int target) {
        if (arr == null || arr.length < 2) {
            return null;
        }
        int[] indices = new int[arr.length];
        int[] res = new int[2];
        for (int i = 0; i < arr.length; i++) {
            indices[i] = i;                     //用来记录每个元素未排序之前的坐标
        }
        sort(arr, indices);                  //自定义一个排序方法,里面包含要排序的数组,及其坐标index
        int l = 0;                          //左右指针
        int r = arr.length - 1;
        while (l < r) {
            if (arr[l] + arr[r] < target) {
                l++;
            } else if (arr[l] + arr[r] > target) {
                r--;
            } else {
                res[0] = indices[l];            //返回所在的位置
                res[1] = indices[r];
                return res;
            }
        }
        return new int[]{-1,-1};
    }

    public static void sort(int[] arr, int[] indices) {   //采用堆排序,时间复杂度O(nlogn)
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, indices, i);
        }
        int size = arr.length;
        swap(arr, indices, 0, --size);
        while (size > 0) {
            heaptify(arr, indices, 0, size);
            swap(arr,indices,0,--size);
        }
    }

    private static void heaptify(int[] arr, int[] indices, int i, int size) {
        int left = i * 2 + 1;
        int right = i * 2 + 2;
        int largest = i;
        while (left < size) {
            if (arr[largest] < arr[left]) {
                largest = left;
            }
            if (right < size && arr[right] > arr[largest]) {
                largest = right;
            }
            if (largest != i) {
                swap(arr, indices, i, largest);
            } else {
                break;
            }
            i = largest;
            left = i * 2 + 1;
            right = i * 2 + 2;

        }
    }

    public static void heapInsert(int[] arr, int[] indices, int i) {
        while (i != 0) {
            int parent = (i - 1) / 2;
            if (arr[parent] < arr[i]) {
                swap(arr, indices, parent, i);
                i = parent;
            } else {
                break;
            }

        }
    }

    private static void swap(int[] arr, int[] indices, int index1, int index2) { //元素交换的时候,也要记录对应下标的交换
        int tmp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = tmp;
        tmp = indices[index1];
        indices[index1] = indices[index2];
        indices[index2] = tmp;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值