双创中心-三

关于周日的算法题的一些想法跟代码:

1、给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

分析:

第一眼看到这个题目太简单了,根本就是送分的,直接就双重循环直接遍历就好了么,显然既然这个是算法训练题就应该有一些提高,不应该只是简单的便利就完事了,这样代码的时间复杂度就会很高,去面试人家的公司也不会聘用这样的小白。

所以:方法一:双重循环遍历

既然大家都会,我就不在这里占用时间来写,

方法二:

首先是一个特例,对于一个升序的数组来说,可以两端向中间进行查找,即开始元素跟结束元素进行相加进行判断,当两数之和小于目标数,开始元素后移,如果两数之和大于目标数,则结尾元素后移。

但是这个只是一个特例,对于无序数组来说,首先应对数组进行排列,记录数组的原始下标,然后对选出的元素与原始下标进行一一对应,哎不说了,有点麻烦,看代码吧

public int[] sum(int[] nums, int target) {
    int[] result = {0, 0};

    Node[] tmp = new Node[nums.length];
    for (int i = 0; i < nums.length; i++) {
        tmp[i] = new Node(nums[i], i+1);
    }

    Arrays.sort(tmp);

    int lo = 0;
    int hi = nums.length - 1;


    while (lo < hi) {
        if (tmp[lo].val + tmp[hi].val == target) {

            if (tmp[lo].idx > tmp[hi].idx) {
                result[0] = tmp[hi].idx;
                result[1] = tmp[lo].idx;
            } else {
                result[0] = tmp[lo].idx;
                result[1] = tmp[hi].idx;
            }
            break;
        } else if (tmp[lo].val + tmp[hi].val > target) {
            hi--;
        } else {
            lo++;
        }
    }
    return result;

由于个人水平有限,又去百度了另一个答案,

方法通过O(n)的时间复杂度完成要求。第一遍O(n)的算法将每个数据a对应的target-a建立查询的数据结构,例如Hash表;第二遍遍历时,查询每个数是否在Hash表中,每次查询时间复杂度为O(1),总的时间复杂度是O(n)。但是Hash表将需要一定的存储空间,为了节省空间,我们可以采用bitmap的方法来最大化的压缩空间复杂度。



class Solution {
    public int[] twoSum(int[] nums, int target) {
         if (nums == null) {
            return null;
        }
        HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; i++) {
            if (hashMap.containsKey(nums[i])) {//当map中有值需要当前值时,说明找到结果。
                return new int[]{hashMap.get(nums[i]), i};
            }
            hashMap.put(target - nums[i], i);
            //存入当前值所需要的数值,比如target为5,当前值为1,他需要4,才能得到目标值。
        }
        return null;
    }
}
2、

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

分析:本题其实是一个大数相加问题,题目本身难度不大,需要考虑以下几个方面: 1. 设计好数据结构,反序存储数字,如数字932存储为2 -> 3 -> 9;

就是应该注意一下几点:

  1. 链表对应结点相加时增加前一个结点的进位,并保存下一个结点的进位;
  2. 两个链表长度不一致时,要处理较长链表剩余的高位和进位计算的值;
  3. 如果最高位计算时还产生进位,则还需要添加一个额外结点。

则具体的代码如下

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
         ListNode c1 = l1;
        ListNode c2 = l2;
        ListNode sentinel = new ListNode(0);
        ListNode d = sentinel;
        int sum = 0;
        while (c1 != null || c2 != null) {
            sum /= 10;
            if (c1 != null) {
                sum += c1.val;
                c1 = c1.next;
            }
            if (c2 != null) {
                sum += c2.val;
                c2 = c2.next;
            }
            d.next = new ListNode(sum % 10);
            d = d.next;
        }
        if (sum / 10 == 1)
            d.next = new ListNode(1);
        return sentinel.next;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值