IT技术小屋

秋风秋雨,皆入我心

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  38 随笔 :: 1 文章 :: 19 评论 :: 0 Trackbacks

#

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.
OJ's undirected graph serialization:
Nodes are labeled uniquely.
We use # as a separator for each node, and , as a separator for node label and each neighbor of the node.
As an example, consider the serialized graph {0,1,2#1,2#2,2}.
The graph has a total of three nodes, and therefore contains three parts as separated by #.
1. First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
2. Second node is labeled as 1. Connect node 1 to node 2.
3. Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.

Visually, the graph looks like the following:
       1
      / \
     /   \
    0 --- 2
         / \
         \_/

需要对原图进行BFS搜索,其中Set<UndirectedGraphNode> visited对已经访问过的节点进行记录,Map<UndirectedGraphNode, UndirectedGraphNode> map用来记录新老节点的对应关系。代码实现如下:
 1 import java.util.HashMap;
 2 import java.util.HashSet;
 3 import java.util.LinkedList;
 4 import java.util.Map;
 5 import java.util.Queue;
 6 import java.util.Set;
 7 
 8 public class CloneGraph {
 9     public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
10         if (node == null)
11             return node;
12         Queue<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();
13         queue.add(node);
14         Set<UndirectedGraphNode> visited = new HashSet<UndirectedGraphNode>();
15         Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
16         while (!queue.isEmpty()) {
17             UndirectedGraphNode n = queue.remove();
18             if (visited.contains(n))
19                 continue;
20             visited.add(n);
21             UndirectedGraphNode clone;
22             if (!map.containsKey(n)) {
23                 clone = new UndirectedGraphNode(n.label);
24                 map.put(n, clone);
25             } else {
26                 clone = map.get(n);
27             }
28             for (UndirectedGraphNode child : n.neighbors) {
29                 queue.add(child);
30                 UndirectedGraphNode cloneChild;
31                 if (!map.containsKey(child)) {
32                     cloneChild = new UndirectedGraphNode(child.label);
33                     map.put(child, cloneChild);
34                 } else {
35                     cloneChild = map.get(child);
36                 }
37                 clone.neighbors.add(cloneChild);
38             }
39         }
40         return map.get(node);
41     }
42 }
posted @ 2013-12-19 10:36 Meng Lee 阅读(962) | 评论 (0)编辑 收藏

There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. 

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station's index if you can travel around the circuit once, otherwise return -1.

Note: The solution is guaranteed to be unique.

首先,这个题目要明确如果gas[0] + gas[1] + ... + gas[n] >= cost[0] + cost[1] + .. + cost[n],那么这个题目一定有解。因为,根据条件移项可得:
(gas[0] - cost[0]) + (gas[1] - cost[1]) + ... + (gas[n] - cost[n]) >= 0,由于最终结果大于等于零,因此一定可以通过加法交换律,得到一个序列,使得中间结果都为非负。因此可以将算法实现如下:
 1 public class GasStation {
 2     public int canCompleteCircuit(int[] gas, int[] cost) {
 3         int sum = 0, total = 0, len = gas.length, index = -1;
 4         for (int i = 0; i < len; i++) {
 5             sum += gas[i] - cost[i];
 6             total += gas[i] - cost[i];
 7             if (sum < 0) {
 8                 index = i;
 9                 sum = 0;
10             }
11         }
12         return total >= 0 ? index + 1 : -1;
13     }
14 }
posted @ 2013-12-19 09:29 Meng Lee 阅读(373) | 评论 (1)编辑 收藏

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
    1. Only one letter can be changed at a time
    2. Each intermediate word must exist in the dictionary
For example,
Given:
    start = "hit"
    end = "cog"
    dict = ["hot","dot","dog","lot","log"]
    As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
    return its length 5.
Note:
    1. Return 0 if there is no such transformation sequence.
    2. All words have the same length.
    3. All words contain only lowercase alphabetic characters.

第一个思路是遍历dict中的每一个元素,看是不是和当前word只相差一个字符,如果是则作为新的当前word,直到当前word与target只相差一个字符。实现代码如下:
 1 public class Solution {
 2     public int ladderLength(String start, String end, HashSet<String> dict) {
 3         HashSet<String> trash = new HashSet<String>();
 4         return searchWordLadder(start, end, dict, trash) + 1;
 5     }
 6 
 7     private int searchWordLadder(String start, String end, HashSet<String> dict, HashSet<String> trash) {
 8         if (stringDiff(start, end) == 1) return 1;
 9         if (dict.size() == trash.size()) return 0;
10         int steps = Integer.MAX_VALUE;
11         for (String word : dict) {
12             if (!trash.contains(word) && stringDiff(start, word) == 1) {
13                 trash.add(word);
14                 int lt = searchWordLadder(word, end, dict, trash);
15                 if (lt != 0 && lt < steps) {
16                     steps = lt;
17                 }
18                 trash.remove(word);
19             }
20         }
21         return steps == Integer.MAX_VALUE ? 0 : steps + 1;
22     }
23     
24     private int stringDiff(String s1, String s2) {
25         int diff = 0;
26         int length = s1.length();
27         for (int i = 0; i < length; i++) {
28             if (s1.charAt(i) != s2.charAt(i)) {
29                 diff++;
30             }
31         }
32         return diff;
33     }
34 }
这个算法可以通过小数据测试,但是在大数据下报超时错误。主要问题是算法复杂度较高,由于dict中的单词是乱序的,因此最坏情况下需要遍历所有可能的转换路径才能做出判断。
改变思路,其实可以通过trie树的BFS搜索获得结果,由于BFS是分层遍历的,因此找到一个解之后就可以马上返回,复杂度是O(N),N是原单词的长度。实现代码如下:
 1 public class WordLadder {
 2     public int ladderLength(String start, String end, HashSet<String> dict) {
 3         if (dict.size() == 0)
 4             return 0;
 5         int currentLevel = 1;
 6         int nextLevel = 0;
 7         int step = 1;
 8         boolean found = false;
 9         Queue<String> st = new LinkedList<String>();
10         HashSet<String> visited = new HashSet<String>();
11         st.add(start);
12         while (!st.isEmpty()) {
13             String s = st.remove();
14             currentLevel--;
15             if (stringDiff(s, end) == 1) {
16                 found = true;
17                 step++;
18                 break;
19             } else {
20                 int length = s.length();
21                 StringBuffer sb = new StringBuffer(s);
22                 for (int i = 0; i < length; i++) {
23                     for (int j = 0; j < 26; j++) {
24                         char c = sb.charAt(i);
25                         sb.setCharAt(i, (char) ('a' + j));
26                         if (dict.contains(sb.toString())
27                                 && !visited.contains(sb.toString())) {
28                             nextLevel++;
29                             st.add(sb.toString());
30                             visited.add(sb.toString());
31                         }
32                         sb.setCharAt(i, c);
33                     }
34                 }
35             }
36             if (currentLevel == 0) {
37                 currentLevel = nextLevel;
38                 nextLevel = 0;
39                 step++;
40             }
41         }
42         return found ? step : 0;
43     }
44 
45     private int stringDiff(String s1, String s2) {
46         int diff = 0;
47         int length = s1.length();
48         for (int i = 0; i < length; i++) {
49             if (s1.charAt(i) != s2.charAt(i)) {
50                 diff++;
51             }
52         }
53         return diff;
54     }
55 }
其中利用了队列对trie树进行BFS。
posted @ 2013-12-19 09:11 Meng Lee 阅读(1514) | 评论 (0)编辑 收藏

VS 2010中添加C++目录的功能已经被否决,可以通过添加User Property Sheet的方法来添加。

例如,添加Microsoft.Cpp.Win32.user.props:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
<PropertyGroup>
    
<ExecutablePath>$(VCInstallDir)PlatformSDK\bin;$(VSInstallDir)\SDK\v2.0\bin;$(ExecutablePath)</ExecutablePath>
    
<IncludePath>$(VCInstallDir)PlatformSDK\include;D:\Work\SQLite\SourceCode\sqlite-amalgamation-3_6_19;Z:\Common;C:\jdk1.6.0_02\include;$(IncludePath)</IncludePath>
    
<ReferencePath>$(ReferencePath)</ReferencePath>
    
<LibraryPath>$(VCInstallDir)PlatformSDK\lib;Z:\Lib;$(LibraryPath)</LibraryPath>
    
<SourcePath>$(SourcePath)</SourcePath>
    
<ExcludePath>$(VCInstallDir)PlatformSDK\include;$(ExcludePath)</ExcludePath>
  
</PropertyGroup>
</Project>

属性文件存放的位置是:
%USERPROFILE%\Local Settings\Application Data\Microsoft\MSBuild\v4.0

那么,这个属性文件会应用到Win32平台下所有的CPP项目中去。 
posted @ 2011-08-15 10:55 Meng Lee 阅读(2591) | 评论 (2)编辑 收藏

     摘要: 学习Ruby on Rails已经一段时间了,一直使用自带的WEBrick服务器进行开发。WEBrick是一款纯Ruby编写的服务器,使用方便,很适合开发环境下进行系统调试。但是它不支持多线程访问,换句话说,所有的Ruby请求都是按照到达的时间先后,顺序处理的,因此效率不高,无法应用在实际的生产环境中。所以今天研究了一下如何将Rails3应用部署到真实的线上环境中。  阅读全文
posted @ 2011-08-02 10:25 Meng Lee 阅读(1685) | 评论 (0)编辑 收藏

     摘要: 最近决定开始阅读Linux 0.11的源代码。学习Linux操作系统的核心概念最好的方法莫过于阅读源代码。而Linux当前最新的源代码包已经有70MB左右,代码十分庞大,要想深入阅读十分困难。而Linux早期的0.11版本虽然有诸多局限,但是具备了现代操作系统的完备功能,一些基本概念沿用到了当前版本,并且代码只有300KB,非常适合阅读。  阅读全文
posted @ 2011-08-02 10:05 Meng Lee 阅读(3122) | 评论 (1)编辑 收藏

周末用了下新浪微博开放平台API和官方发布的Java客户端,感觉可以用两个字形容:坑爹!

先说说遇到的几个极其弱智的bug吧:

1)分页

官方API文档里面对数据分页获取的说明是使用cursor和count这两个参数。其中,cursor指明了起始记录的位置,而count指明了当前每页的记录条数,请求第一页的时候cursor为-1。返回结果会给出next_cursor,指明下一页的起始位置。

这个设计看起来不错,问题是根据这个文档,得到的结果会有重复。也就是说同一条记录会出现在多个页面中,而且这种重复出现的频率是随机的。试想连程序的行为都无法预测,叫别人怎么开发应用?!

更搞笑的是,官方发布的Java客户端居然把cursor写成了page,导致了不管怎么设置参数,返回的都是很多重复的数据,但重复的比例又是随机的!难道新浪没有对这个客户端进行过简单的测试就发布了吗?无法想象!!

2)返回结果的解析

好不容易把用户信息得到了,新浪自己写了一个JavaBean用来表示一个User的信息。问题是把JSON解析成Java对象的时候,居然把布尔属性字段解析错了,导致每次返回都是false,好不容易得到的数据就这么泡汤了~~难道解析JSON很难嘛??敢测试下再发布吗?

3)诡异的负数

我小学学到的知识告诉我,人的个数不可能是负数。于是我天真的在followers_count这个数据库字段上加了unsigned,本以为教数据库的老师应该很开心吧,这孩子设计的数据库还蛮严谨的,而且应该能够和新浪的数据很好地匹配。

于是我开心的运行程序,诡异的错误出现了:超出字段范围。晕,于是检查所有数字字段是否超过了表示范围,N遍检查过后确认数据库没问题,纠结~~于是看log,发现返回的数据里面,有一个项的followers_cout字段是-2,负数!!!尼玛这人虽然粉丝少了点,也不至于欠你新浪两个粉丝吧,我当时就凌乱了,于是加了很多异常数据的判断和检查。。。

4)诡异的版权信息

Java客户端里面很多文件的作者信息是:@author Yusuke Yamamoto - yusuke at mac.com,感觉这应该是一个苹果公司的员工开发的,然后新浪拿过来,没有code review,没有测试,就直接官方发布了。。。

这样不重视代码质量,把产品构建在志愿者的贡献之上,我觉得是新浪的耻辱,更是中国互联网产业的顽症恶疾。

以上只是我这两天试用了一小部分API的感受。由于各种bug,我不得不阅读源代码,并根据我的需求改写代码,甚至一度我准备抛弃这个客户端,直接用HTTP调用。反正最后严重降低了我的效率。

回想起这两天传高铁出事是程序员的问题,我看要按照新浪这质量标准,不知道还要出什么大事~~

 

posted @ 2011-07-31 20:49 Meng Lee 阅读(3792) | 评论 (11)编辑 收藏

     摘要: Axis2/C是一个用C语言实现的Web Service引擎。 Axis2/C基于Axis2架构,支持SOAP1.1和SOAP1.2协议,并且支持RESTful风格的Web Service。基于Axis2/C的Web Service可以同时暴露为SOAP和RESTful风格的服务。 最近研究了一下Axis2/C,这篇文章详述了如何利用Axis2/C发布一个Web Service,并通过...  阅读全文
posted @ 2011-07-05 16:33 Meng Lee 阅读(3823) | 评论 (1)编辑 收藏

Memcached是被广泛使用的分布式缓存技术。不同的语言有不同的Memcached客户端程序,对于Java客户端来说,首推Memcached Java Client(http://github.com/gwhalin/Memcached-Java-Client )。

这次,Memcached Java Client推出的2.6.1发布版是基于全新的performance分支,具有如下重大改进:

  1. 较之老版本,在性能上有300%左右的提升;
  2. 兼容老版本,用户无须修改自己的源代码;
  3. 支持多个memcached协议,包括text,udp和binary协议;
  4. 支持SASL认证机制;
  5. 重新实现的连接池,修复了之前的连接数太多所导致的OutOfMemory异常;
  6. 加入了slf4j logger支持,使得开发人员可以方便的记录日志;
  7. 支持自定义的对象序列化方法。

这个分支由Schooner Information Technology贡献,并由Schooner中国团队完成开发,可以通过以下邮箱联系作者:jowett.lee@gmail.com

可以从这里下载二进制包:https://github.com/gwhalin/Memcached-Java-Client/downloads 
源代码在github上,http://github.com/gwhalin/Memcached-Java-Client ,然后选择performance分支。

下面是一些性能测试的数据,包括了当前流行的Memcached Java Client。其中,schooner指的是这个分支的text protocol, schooner_bin指的是binary protocol,链接是:https://github.com/gwhalin/Memcached-Java-Client/wiki/PERFORMANC

转载请注明出处:http://www.blogjava.net/menglee/archive/2011/06/29/353375.html


posted @ 2011-06-29 18:09 Meng Lee 阅读(2442) | 评论 (2)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4