# 题目

1. Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

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

Example:

, , , ], target = ,

Because nums[] + nums[] =  +  = ,
, ].

UPDATE (2016/2/13):
The return format had been changed to zero-based indices. Please read the above updated description carefully.

# 思路

尝试暴力破解,(两个for循环)时间复杂度O(n^2)空间复杂度O(1)623ms

        // brute force: time O(n^2) space O(1) result: 632ms
        public int[] TwoSum(int[] nums, int target)
        {
            ; i < nums.Length; i++)
                ; j < nums.Length; j++)
                    if (nums[i] + nums[j] == target) return new int[] { i, j };
            throw new Exception("no answer");
        }
        

慢在哪里?和结果无关的计算太多

举个例子,假设nums = {7, 2, 4, 6, 3},target = 8,即answer = {1, 3}。

暴力破解方法,对于1,计算了4  * 3 = 12次。真正有用的只有1次。计算的结果有些结果偏大,有些结果偏小,谷需要动态调整搜索的位置。

改进算法:

  1. 复制数组
  2. 复制的数组排序
  3. start指向复制的nums开头,表示answer较小元素在排序数组里的下标;end指向复制的nums结尾,表示answer较大元素在排序数组里的下标
  4. if start < end,表示target搜索未结束,转4,else 转8
  5. if start指针元素 + end指针元素 > target,说明start指针元素太小,start指针右移,返回3
  6. if start指针元素 + end指针元素 < target,说明end指针元素太大,end指针左移,返回3
  7. if start指针元素 + end指针元素 == target,说明找到满足target的answer,start指针右移,转8
  8. 取出start和end指针对应的元素,在nums中搜索并保存下标
  9. 输出下标组

技巧性搜索,(取最长的快速排序时间时间复杂度O(nlgn)空间复杂度O(n)时间500ms

        // sort first, get left part and right part tricky, find left index and right index
        // time: O(nlgn) space: O(n) 500ms
        // reference: https://github.com/yangliguang yangliguang
        public int[] TwoSum(int[] nums, int target)
        {
            int[] copy = new int[nums.Length];
            Array.Copy(nums, copy, nums.Length);
            Array.Sort(copy); // O(nlgn)
            , end = copy.Length - , left = , right = ;

            while (start < end) // O(n)
            {
                if (copy[start] + copy[end] == target)
                {
                    left = copy[start];
                    right = copy[end];
                    break;
                }
                else if (copy[start] + copy[end] < target)
                {
                    start++;  // very tricky
                }
                else
                {
                    end--; // very tricky
                }
            }

            start = end = -;
            ; i < nums.Length; i++)
            {
                if (nums[i] == left)
                {
                    start = i;
                    break;
                }
            }

            ; i >= ; i--)
            {
                if (nums[i] == right)
                {
                    end = i;
                    break;
                }
            }
            if (start > end) return new int[] { end, start };
            else return new int[] { start, end };
        }

还有另一种想法。

举个例子,举个例子,假设nums = {7, 2, 4, 6, 3},target = 8,即answer = {1, 3}。

我们随意挑出一个数,7,也就是说,我们只需要找到1,然而nums中没有1。再挑出6,nums中有2,满足条件,输出下标。

根据上述,可以设计算法:每次先取出一个数n,用target - n,查看与n配对的元素是否存在,存在就输出两个数的下标;不存在就

小细节:放入集合时,可以用Map连带放入下标,这样就不必再去搜索下标。

综合上述,我们选用Hashtable来完美的完成此题。

# 解决(Hashtable)

Hashtable时间复杂度O(n)空间复杂度O(n)运行时间496ms

        // right hash: time O(n) (degenerate when collison occured) ususlly O(1) (insert and search) space: O(n) result: 496ms
        public int[] TwoSum(int[] nums, int target)
        {
            ];
            System.Collections.Hashtable table = new System.Collections.Hashtable(nums.Length);  // use empty constructor, result: 544 ms
            ; i < nums.Length; i++)
            {
                int another = target - nums[i];
                if (table.ContainsKey(another))
                {
                    int anotherIndex = (int)table[another];
                    result[] = anotherIndex > i ? i : anotherIndex;
                    result[] = anotherIndex < i ? i : anotherIndex;
                    return result;
                }
                else
                {
                    if (!table.Contains(nums[i])) table.Add(nums[i], i);
                }
            }

            throw new Exception("no answer");
        }

# 题外话

这也是一段用Hashtable思想写的一段代码,我把它标记为bad hash,各位可以仔细推敲一下这里的问题(参考下面的测试用例)。

        // bad hash: ignore duplication
        public int[] TwoSum(int[] nums, int target)
        {
            System.Collections.Hashtable table = new System.Collections.Hashtable(nums.Length);
            ; i < nums.Length; i++)
                 table.Add(nums[i], i); // key can have duplications, so hash like this is a bad idea

            ; i < table.Count; i++)
            {
                int another = target - nums[i];
                if (table.ContainsKey(another) && another != nums[i]) return new int[] { i, (int)table[another] };
            }
            throw new Exception("no answer");
        }

# 测试用例

        static void Main(string[] args)
        {
            _1TwoSum solution = new _1TwoSum();

            Debug.Assert(Test.match(solution.TwoSum(, ,  }, ), ,  }), "wrong 1");
            Debug.Assert(Test.match(solution.TwoSum(, , ,  }, ), ,  }), "wrong 2");
            Debug.Assert(Test.match(solution.TwoSum(,  }, ), ,  }), "wrong 3");
            Debug.Assert(Test.match(solution.TwoSum(, , ,  }, ), ,  }), "wrong 4"); // duplication is result
            , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,  };
            ;
            Debug.Assert(Test.match(solution.TwoSum(test, target), ,  }), "wrong 5"); // duplication isn't result
            Debug.Assert(Test.match(solution.TwoSum(, , , , , ,  }, ), ,  }), "wrong 6");
        }
    class Test
    {
        public static bool match(Array result, Array expect)
        {
            Debug.Assert(result.Length == expect.Length, "result's length isn't equal to expect's length");

            ; i < result.Length; i++)
                if (!result.GetValue(i).Equals(expect.GetValue(i))) return false;
            return true;
        }
    }

# 链接

Q: https://leetcode.com/problems/two-sum/

A: https://github.com/mofadeyunduo/LeetCode/tree/master/1TwoSum

(请多多支持我刚刚建立的GitHub和博客,谢谢,有问题可以邮件609092186@qq.com或者留言,我尽快回复)

LeetCode-1TwoSum(C#)的更多相关文章

  1. leetCode算法——1TwoSum(两数之和)

    描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中 ...

  2. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  3. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

  4. [LeetCode] Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串

    Find the length of the longest substring T of a given string (consists of lowercase letters only) su ...

  5. Leetcode 笔记 113 - Path Sum II

    题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...

  6. Leetcode 笔记 112 - Path Sum

    题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...

  7. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  8. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  9. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  10. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

随机推荐

  1. JavaScript 对数据处理的5个API

    JavaScript对数据处理包括向上取整.向下取整.四舍五入.固定精度和固定长度5种方式,分别对应ceil,floor,round,toFixed,toPrecision等5个API,本文将对这5个 ...

  2. 微信小程序体验(2):驴妈妈景区门票即买即游

    驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...

  3. SQL Server-聚焦APPLY运算符(二十七)

    前言 其实有些新的特性在SQL Server早就已经出现过,但是若非系统的去学习数据库你会发现在实际项目中别人的SQL其实是比较复杂的,其实利用新的SQL Server语法会更加方便和简洁,从本节开始 ...

  4. C#多线程之线程同步篇1

    在多线程(线程同步)中,我们将学习多线程中操作共享资源的技术,学习到的知识点如下所示: 执行基本的原子操作 使用Mutex构造 使用SemaphoreSlim构造 使用AutoResetEvent构造 ...

  5. UWP开发之Mvvmlight实践七:如何查找设备(Mobile模拟器、实体手机、PC)中应用的Log等文件

    在开发中或者后期测试乃至最后交付使用的时候,如果应用出问题了我们一般的做法就是查看Log文件.上章也提到了查看Log文件,这章重点讲解下如何查看Log文件?如何找到我们需要的Packages安装包目录 ...

  6. 在centos7上安装ClamAV杀毒,并杀毒(centos随机英文10字母)成功

    前言 上传文件的时候发现总是失败,查看top发现有个进程一直cpu占用80%以上,而且名称还是随机数.kill之后,一会儿又重新生成了.突然发现居然没有在服务端杀毒的经历.在此处补齐. 安装clama ...

  7. 设计模式C#合集--工厂方法模式

    简单工厂,代码: public interface ISpeak { public void Say(); } public class Hello : ISpeak { public void Sa ...

  8. Android中常见的图片加载框架

    图片加载涉及到图片的缓存.图片的处理.图片的显示等.而随着市面上手机设备的硬件水平飞速发展,对图片的显示要求越来越高,稍微处理不好就会造成内存溢出等问题.很多软件厂家的通用做法就是借用第三方的框架进行 ...

  9. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  10. CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能

    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...