LeetCode-Algorithms #001 Two Sum, Database #175 Combine Two Tables

Posted chang4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode-Algorithms #001 Two Sum, Database #175 Combine Two Tables相关的知识,希望对你有一定的参考价值。

最近两周一直感觉学习比较松懈, 打算加大一点强度, 从今天开始, 希望能在每天正常进度完成后在LeetCode上选一两题写一写, 同时学习一下高手的做法.

 

LeetCode - Algorithms #001 Two Sum

技术分享图片

给定一个整数数组, 找出其中两个元素, 使其和等于目标值, 返回这两个元素在原数组中的索引组成的数组. 可以假设有且只有一组正解, 且每个元素只能使用一次.

 

我的思路:

其实想不到什么好的方法, 遍历就好, 非常素朴的回答:

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3         //根据题目设定, nums的长度必大于等于2, 所以也不用考虑什么特殊情况
 4         //结论所需的两个索引, i从0开始遍历, j从1开始遍历
 5         int i = 0,j = 1;
 6         outer: for(i = 0; i < nums.length - 1; i++){
 7             for(j = i + 1; j < nums.length; j++){
 8                 //找到答案就跳出外循环
 9                 if(nums[i] + nums[j] == target){
10                     break outer;
11                 }
12             }
13         }
14         //把答案装进数组然后返回
15         int[] ans = {i,j};
16         return ans;
17     }
18 }

技术分享图片

结果顺利通过, 用时28ms, 只有30%的用户比我还慢, 看来是写得很差了??

再来看看大神们是怎么做的, 柱状图里面最高的那一条是用时4ms的例子, 拿来看看(注释是我加的):

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3         //先创建一个长度为2的整数数组用来装答案
 4         int[] result = new int[2];
 5         //再创建一个key和value都为整数类型的HashMap
 6         Map<Integer,Integer> m = new HashMap<Integer, Integer>();
 7         //从0开始对nums进行遍历
 8         for(int i = 0; i < nums.length; i++) {
 9             //当i=0的时候,m为空,所以下面if语句一定无法满足条件,直接走else把(nums[0],0)存入m;
10             //从i=1之后的情形开始,判断目标值减去当前的nums[i]是否已经包含在了m的keySet中,
11             //如果包含,就把它的索引找出放入result[0]中,把i放入result[1]中,跳出循环,
12             //如果不包含,就把(nums[i],i)加入m,继续遍历
13             if(m.containsKey(target - nums[i])){
14                 result[0] = m.get(target - nums[i]);
15                 result[1] = i;
16                 break;
17             } else {
18                 m.put(nums[i], i);
19             }
20         }
21         //返回结果
22         return result;
23     }
24 }

确实是非常有巧思的做法, 几乎没有处理过算法问题, 我无论如何也想不到用HashMap来处理此类问题

在我写的遍历中, i每增加1, 都要对剩下的值进行一一匹配测试, 上面这个写法就用HashMap自带的检验方法测试一次就好了, 而且hash表结构在查找数据的时候速度是非常快的

但是能快这么多我确实没有想到, 现在也不是特别理解??

 

最后来看看2ms完成的大神飘逸的思路,我花了将近一个小时才读明白,注释写得不怎么清楚,不过尽力了??

大神从头到尾都没有用过超过java基础第一周的内容:

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3         //先把原数组的长度存为常数il
 4         final int il = nums.length;
 5         //System.out.println("array length: " + nums.length);
 6         //int il2 = (il >> 2) -1 ;
 7         //arrayLen/4 - 1
 8         //System.out.println("il2: " + il2);
 9         int pot = 4096;
10         //while((il2 >>= 1) > 0) pot <<= 1;
11         //大神拿来做位运算用的常数4095, 也就是二进制的1111 1111 1111
12         //看排名第二的答案, 这个常数是根据数组长度生成的, 这里选4096应该是大神为了冲击最快手动选定的最适合本题的长度
13         final int bitMod = pot - 1;
14         
15 
16         //System.out.println("bitMod: " + bitMod);
17         //System.out.println("pot: " + pot);
18         
19                 
20         //一个长度为4096的"篮子"
21         final int[] bucket = new int[pot];
22         //一个与原数组长度相同的"链"
23         final int[] linked = new int[il];
24         //把原数组第一个元素存为常数
25         final int firstVal = nums[0];
26         //从第二个元素开始遍历
27         for (int i = 1; i < il; i++) {
28             //目前的元素值
29             int currNum = nums[i];
30             //目标值和元素值的差
31             int complement = target - currNum;
32             
33             //如果差恰好等于第一个元素值,就直接返回结果
34             if (complement == firstVal) {
35                 return new int[] { 0, i };
36             }
37             
38             //这里的complement & bitMod的结果应该是等价于
39             //i > 4095 ? (i % 4096) : i 或者其实也就是
40             //i % 4096
41             //只不过运行效率要快得多
42             //所以这里做得就是把差值对4096的余数放在这个篮子里
43             int complementLLIndex = bucket[complement & bitMod];
44 
45             //当这个篮子里对应的位置不为空的时候, 就证明这个所需要的差值(或与之同余的值)之前已经遍历过了
46             while(complementLLIndex != 0) {
47                 //这个篮子里面的对应位置应该存储的是所需差值在原数组中的索引,进行检验
48                 if(nums[complementLLIndex] == complement) {
49                     //Found
50                     //如果是就找到了
51                     return new int[] { complementLLIndex, i };
52                 }
53                 //如果不是, 说明找到的不是对应的差值, 只不过是和对应的差值同余的值, 
54                 //继续通过linked中存储的上一个索引进行匹配
55                 complementLLIndex = linked[complementLLIndex];
56                 //如果都不行说明找到的全都是同余的值,而没有匹配值,跳出循环继续遍历
57             }
58             //使当前值对4096取余
59             int currNumLLIndex = currNum & bitMod;
60             //把篮子中上面那个余数值位置的值存入linked[i]
61             linked[i] = bucket[currNumLLIndex];
62             //再让篮子里上面那个mod位置的值为i
63             bucket[currNumLLIndex] = i;
64 
65         }
66         return null; 
67     }
68 }

可能是我少见多怪, 总之就是强

这题就先到这里

 

LeetCode - Database #175 Combine Two Tables

数据库的第一题

技术分享图片

技术分享图片

非常简单的连表查询, 只要记得满足题目要求, 记得使用LEFT OUTER JOIN即可:

1 # Write your mysql query statement below
2 SELECT Person.FirstName, Person.LastName, Address.City, Address.State
3 FROM Person LEFT OUTER JOIN Address
4     ON Person.PersonId = Address.PersonId;

顺利通过:

技术分享图片

 

这题其实也没什么好说的, 大家写得都差不多, 贴一个代表性的回答, 提醒自己对表可以使用别名进行操作:

1 # Write your MySQL query statement below
2 select P.FirstName, P.LastName, A.City, A.State 
3 from Person P Left Join Address A 
4 ON P.PersonId = A.PersonId;

 

以上是关于LeetCode-Algorithms #001 Two Sum, Database #175 Combine Two Tables的主要内容,如果未能解决你的问题,请参考以下文章

leetcode-algorithms-92. Reverse Linked List II

leetcode-algorithms-109. Convert Sorted List to Binary Search Tree

LeetCode-Algorithms 1. 两数之和

LeetCode-Algorithms #007 Reverse Integer, Database #182 Duplicate Emails

LeetCode-Algorithms #005 Longest Palindromic Substring, Database #179 Consecutive Numbers

LeetCode-Algorithms #003 Longest Substring Without Repeating Characters, Database #177 Nth Highest S