Design and implement a TwoSum class. It should support the following operations: add and find.

add - Add the number to an internal data structure.
find - Find if there exists any pair of numbers which sum is equal to the value.

这个解法很容易想到,但很容易超时。

基本来说有这样几个途径去解。

第一种,使用一个数组去存所有加入的元素,使用一个Set去存所有的和。在实现Find的时候,遍历数组,把能够得到的和都加到set中去。这样,find的时间复杂度是O(1)了,因为只需要判断value是否在集合里面,但是add就变成了O(n)。实践证明这是行不通的。

第二种,还是使用一个数组去存元素,但是每次加入的时候保持数组有序,这样虽然可以通过二分查找找到插入点,但是插入本身,由于是在数组中,复杂度就变成O(n)了。在实现Find的时候,使用TwoSum标准算法(用两个指针,一前一后遍历)。所以这个也没有好多少,还是会超时。

第三种,不要使用数组了。使用一个Search Tree来存放元素。这样在add的时候可以基本保证O(logn)。

Find怎么办呢?

其实也可以采用TwoSum的那个标准算法,但是需要在TreeNode里面存放一个pre和next指针,分别是排序后的,该节点的前一个和后一个元素。这样你远看是一颗树,近看是双向链表。

在二叉排序树中插入一个节点大家都会,要注意的是如何在插入的过程中,记录pre和next。其实只要是向右搜索,我们就给pre赋值,向左搜索就给next赋值就可以了。

哦,对了,还要在插入过程中注意update 双向链表的head和tail,这个也很容易,只要插入后发现pre是null,那么这个节点肯定是head嘛,next是null就是tail咯。

代码是这个。

public class TwoSumDS {

    private TreeNode root;
private TreeNode head;
private TreeNode tail; //private Set<Integer> seenSum = new HashSet<>(); public void add(int number) {
if (root == null) {
root = new TreeNode(number);
head = tail = root;
} else {
insertIntoTree(number);
}
} public boolean find(int value) {
{
if (head != null && tail != null && head != tail) {
TreeNode p = head, q = tail;
while (p != q) {
int sum = p.val + q.val;
//seenSum.add(sum);
if (sum > value) {
q = q.pre;
} else if (sum < value) {
p = p.next;
} else {
return true;
}
}
}
}
return false;
} private void insertIntoTree(int val) {
TreeNode p = root;
TreeNode pre = null;
TreeNode next = null;
while (true) {
//seenSum.add(val + p.val);
if (val > p.val) {
pre = p;
if (p.right != null) {
p = p.right;
} else {
p.right = new TreeNode(val);
insertInToChain(p.right, pre, next);
break;
}
} else {
next = p;
if (p.left != null) {
p = p.left;
} else {
p.left = new TreeNode(val);
insertInToChain(p.left, pre, next);
break;
}
}
}
} private void insertInToChain(TreeNode n, TreeNode pre, TreeNode next) {
if (pre != null) {
pre.next = n;
} else {
head = n;
}
if (next != null) {
next.pre = n;
} else {
tail = n;
}
n.pre = pre;
n.next = next;
} private static class TreeNode {
int val;
TreeNode right;
TreeNode left;
TreeNode pre;
TreeNode next;
TreeNode(int val) {
this.val = val;
}
} public static void main(String[] args) {
TwoSumDS ts = new TwoSumDS();
ts.add(1);
ts.add(3);
ts.add(5);
System.out.println(ts.find(4));
System.out.println(ts.find(7));
}
}

注意到撸主注释的部分,有一个优化。就是在插入和搜索过程中,沿途找到的sum我们缓存起来,下次说不定可以用。Find的之前可以先在seenset里面看看。

不过这个优化导致了超时,所以就去掉了。看了一下Java doc,并没有gurantee HashSet的存放操作是O(1)的。

看来Java还没有很多人提交哟:>

LeetCode 笔记27 Two Sum III - Data structure design的更多相关文章

  1. 【LeetCode】170. Two Sum III – Data structure design

    Difficulty:easy  More:[目录]LeetCode Java实现 Description Design and implement a TwoSum class. It should ...

  2. 【leetcode】170. Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:  add and find. add  ...

  3. 【LeetCode】170. Two Sum III - Data structure design 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 数组+字典 平衡查找树+双指针 日期 题目地址:htt ...

  4. 170. Two Sum III - Data structure design【easy】

    170. Two Sum III - Data structure design[easy] Design and implement a TwoSum class. It should suppor ...

  5. [LeetCode] Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:add and find. add - ...

  6. LeetCode Two Sum III - Data structure design

    原题链接在这里:https://leetcode.com/problems/two-sum-iii-data-structure-design/ 题目: Design and implement a ...

  7. LeetCode 170. Two Sum III - Data structure design (两数之和之三 - 数据结构设计)$

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  8. [LeetCode] 170. Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:add and find. add - ...

  9. ✡ leetcode 170. Two Sum III - Data structure design 设计two sum模式 --------- java

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

随机推荐

  1. Android中有时候运行程序的时候会报错:An internal error occurred during:。。。。

    解决办法: Project -> Properties -> Run/Debug Settings: 1. select "Launching New_configuration ...

  2. python 把数据 json格式输出

    有个要求需要在python的标准输出时候显示json格式数据,如果缩进显示查看数据效果会很好,这里使用json的包会有很多操作 import json date = {u'versions': [{u ...

  3. Linux下使用iostat 监视I/O状态

    我们可以使用 sar(1), pidstat(1), mpstat(1), vmstat(8) 来监控 一.安装 yum install sysstat 二.参数解释 FILES /proc/stat ...

  4. 问题解决——ShowWindow不显示窗口

    配合任务栏通知区域. //MFC对话框程序 void CXXXDlg::OnShowHideUi() { // TODO: 在此添加命令处理程序代码 m_bShown=!m_bShown; ShowW ...

  5. jQuery实现联动下拉列表查询框

    <!DOCTaYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org ...

  6. Provides PHP completions for Sublime Text

    来源:https://packagecontrol.io/packages/PHP%20Completions%20Kit php-completions php-completions plugin ...

  7. Redis系列(三)—— 订阅/发布

    Redis 订阅/发布 参考:http://www.cnblogs.com/mushroom/p/4470006.html,http://www.tuicool.com/articles/ABry2a ...

  8. python strip() lstrip() rstrip() 使用方法

    Python中的strip用于去除字符串的首尾字符串,同理,lstrip用于去除最左边的字符,rstrip用于去除最右边的字符. 这三个函数都可传入一个参数,指定要去除的首尾字符. 需要注意的是,传入 ...

  9. STL的erase()陷阱-迭代器失效总结

    下面材料整理自Internet&著作. STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.s ...

  10. uva 725 division(水题)——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABVMAAAOHCAIAAAClwESxAAAgAElEQVR4nOydybGturJFcQEPfgQu4A