posted in OJ题解 

题目

https://oj.leetcode.com/problems/word-search/

分析

  1. 通过递归来实现的DFS搜索。

  2. 需要注意的一点是, 要用一个visited二维vector来记录已经访问的元素, 以后不能再访问了。

  3. visited形参要声明成引用形式, 每次递归后手动的恢复现场。 如果声明成变量的形式, 会超时。

代码

class Solution
{
public:
	bool exist(vector<vector<char>> &board, string word)
	{
		vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false));
		for (int i = 0; i < board.size(); i++)
		{
			for (int j = 0; j < board[0].size(); j++)
			{
				if (board[i][j] == word[0])
					if (search(board, i, j, word, 0, visited))
						return true;
			}
		}
		return false;
	}

	bool search(vector<vector<char>> &board, int i, int j, string word, int index, vector<vector<bool>> &visited)
	{
		if (index == word.size())
			return true;
		else if (i < 0 || i == board.size() || j < 0 || j == board[0].size())
			return false;
		else if (visited[i][j] == true)
			return false;
		else if (board[i][j] != word[index])
			return false;
		else
		{
			visited[i][j] = true;
			if (search(board, i-1, j, word, index+1, visited)) return true;
			if (search(board, i+1, j, word, index+1, visited)) return true;
			if (search(board, i, j-1, word, index+1, visited)) return true;
			if (search(board, i, j+1, word, index+1, visited)) return true;
			visited[i][j] = false;
		}

		return false;
	}
};

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/38826685

posted in OJ题解 

前言:

做到Anagrams这道题, 费了半天劲没明白输入输出要求到底是怎样的。 最后找了两个测试用例终于明白题目要求了。

Input:  ["tea","and","ate","eat","den"]

Output:     ["tea","ate","eat"]

Input:       ["cat","rye","aye","dog", "god","cud","cat","old","fop","bra"]

Output:    ["cat","cat","dog","god"]

题目:

Given an array of strings, return all groups of strings that are anagrams.

Note: All inputs will be in lower-case.

https://oj.leetcode.com/problems/anagrams/

分析:

Anagram可以知道Anagram什么意思, 

要点有两个:

        1. 把每个字符串排序后再处理, 可以判断是否是anagram

        2. 把处理好的数据放到map中, 供下次查询

        3. 注意anagram可能会出现三个一组的

代码:

class Solution
{
public:
    vector<string> anagrams(vector<string> &strs)
    {   
        vector<string> res;
        map<string, int> anagram;

        for (int i = 0; i < strs.size(); i++)
        {
            string s = strs[i];

            sort(s.begin(), s.end());
            if (anagram.find(s) == anagram.end())
                anagram[s] = i;
            else
            {
                //如果是第二个anagram
                if (anagram[s] > -1) 
                {
                    res.push_back(strs[anagram[s]]);
                    anagram[s] = -1; 
                }
                res.push_back(strs[i]);
            }
        }

        return res;
    }   
};

参考:

https://oj.leetcode.com/discuss/215/does-return-groups-return-result-vector-string-return-groups

http://www.cnblogs.com/AnnieKim/archive/2013/04/25/3041982.html

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/38756403

posted in OJ题解 

题目:

https://oj.leetcode.com/problems/generate-parentheses/

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n = 3, a solution set is:

"((()))", "(()())", "(())()", "()(())", "()()()"

分析:

看到题目的之后, 首先在心里模拟生成结果的过程, 比如说n=2时, 首先 生成一个"(", 然后就有两个选择了, 生成"("或")", 再下一步又面临着两个选择。。。以此类推, 每次都有两个选择, 仿佛生成了一棵二叉树。 

Center

这种情况下, 多半要用递归来解决了。递归算法, 最重要的是两点, 一个是找到它终止的边界条件, 一个是找到它每次递归的规律。

首先是终止条件, 显然这个问题的终止条件是, “(”和")"的数量都达到n时,以及")"的数量增长到和"("的数量相等时, 算法就终止了。它的递归规律是, 每次"("的数量或者")"的数量加1。 然后就可以写代码了。

代码:

class Solution
{
public:
    vector<string> generateParenthesis(int n)
    {
		generate(n, 0, 0, "");

		return res;
    }

	void generate(int n, int left, int right, string s)
	{
		if (right == n)
			res.push_back(s);

		if (left < n)
			generate(n, left + 1, right, s + '(');

		if (right < left)
			generate(n, left, right + 1, s + ')');
	}

private:
	vector<string> res;
};

参考:

http://blog.csdn.net/yutianzuijin/article/details/13161721

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/38642115

posted in OJ题解 

前言

Leetcode做到Valid Number这道题, 看到 Leetcode题目分类 中说这道题难度为二级(总共五级), 还以为这道题真的很简单。。。真是坑了大爹了。

仔细总结了下, 这道题大概有三种解法:

题目

https://oj.leetcode.com/problems/valid-number/

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
Note: It is intended for the problem statement to be ambiguous. 

You should gather all requirements up front before implementing one.

解法一:

这种方法用正则表达式来解决, 算是最简单优雅的一种方法了。

class Solution2
{
public:
    bool isNumber(const char *s) 
    {   
<span style="white-space:pre">	</span>regex re("( *)[+-]?(\\d+|\\d+\\.\\d*|\\d*\\.\\d+)([eE][+-]?\\d+)?");

        if (regex_match(s, re))
            return true;
        else
            return false;
    }   

};

不过截止到发文章, g++ 4.8.2貌似还是没有完全支持正则表达式, 所以这段代码编译会报错。

但是如果用Java或Python的话, 应该没问题了。

另一方面, 面试的时候恐怕不会允许简简单单的用正则表达式来解决这个问题, 所以还要掌握其他方法。

解法二:

2.1 DFA

第二种方法用DFA来解决这个问题, 用到了了编译原理中的tokenizer那部分的思想。

这种方法写代码之前要先画出图来才行,我画的如下:

SouthEast

画的有点乱, 不过领会精神就好。 :)

代码如下:

class Solution2_1
{
public:
public:
	bool isNumber(const char *s)
	{
		int state = 0;

		while (1)
		{
			switch (state)
			{
				case 0:
					if (*s == ' ')
						state = 0;
					else if (*s == '+' || *s == '-')
						state = 1;
					else if (isdigit(*s))
						state = 2;
					else if (*s == '.')
						state = 9;
					else 
						state = 8;
					break;

				case 1:
					if (isdigit(*s))
						state = 2;
					else if (*s == '.')
						state = 9;
					else
						state = 8;
					break;

				case 2:
					if (isdigit(*s))
						state = 2;
					else if (*s == '.')
						state = 3;
					else if (*s == '\0')
						state = 7;
					else if (*s == ' ')
						state = 10;
					else if (*s == 'e' || *s == 'E')
						state = 5;
					else
						state = 8;
					break;
					
				case 3:
					if (isdigit(*s))
						state = 4;
					else if (*s == '\0')
						state = 7;
					else if (*s == ' ')
						state = 10;
					else if (*s == 'e' || *s == 'E')
						state = 5;
					else
						state = 8;
					break;

				case 4:
					if (isdigit(*s))
						state = 4;
					else if (*s == 'e' || *s == 'E')
						state = 5;
					else if (*s == '\0')
						state = 7;
					else if (*s == ' ')
						state = 10;
					else
						state = 8;
					break;

				case 5:
					if (isdigit(*s))
						state = 6;
					else if (*s == '+' || *s == '-')
						state = 11;
					else
						state = 8;
					break;

				case 6:
					if (isdigit(*s))
						state = 6;
					else if (*s == ' ')
						state = 6;
					else if (*s == '\0')
						state = 7;
					else if (*s == ' ')
						state = 10;
					else
						state = 8;
					break;

				case 7:
					return true;

				case 8:
					return false;

				case 9:
					if (isdigit(*s))
						state = 4;
					else
						state = 8;
					break;

				case 10:
					if (*s == '\0')
						state = 7;
					else if (*s == ' ')
						state = 10;
					else
						state = 8;
					break;
				case 11:
					if (isdigit(*s))
						state = 6;
					else 
						state = 8;
					break;
			}
			s++;
		}
	}
};

这段代码可能开起来有点长, 不过只要弄明白了那张状态转换图很容易明白的。

2.2 DFA改进版

上面这段代码可能有点长, 所以用二维数组对其进行改进:

SouthEast 1

代码如下:

class Solution2_2
{
public:
	bool isNumber(const char *s)
	{
		int state = 0;
		int translate[][7] =
		{
			0, 1, 2, 8, 9, 8, 8,	//0
			8, 8, 2, 8, 9, 8, 8,	//1
			10, 8, 2, 5, 3, 7, 8,	//2
			10, 8, 4, 5, 8, 7, 8,	//3
			10, 8, 4, 5, 8, 7, 8, 	//4
			8, 11, 6, 8, 8, 8, 8,	//5
			10, 8, 6, 8, 8, 7, 8,	//6
			7, 7, 7, 7, 7, 7, 7,	//7
			8, 8, 8, 8, 8, 8, 8,	//8
			8, 8, 4, 8, 8, 8, 8,	//9
			10, 8, 8, 8, 8, 7, 8, 	//10
			8, 8, 6, 8, 8, 8, 8		//11
		};

		int type;
		while (1)
		{
			if (*s == ' ')
				type = 0;
			else if (*s == '+' || *s == '-')
				type = 1;
			else if (isdigit(*s))
				type = 2;
			else if (*s == 'e' || *s == 'E')
				type = 3;
			else if (*s == '.')
				type = 4;
			else if (*s == '\0')
				type = 5;
			else 
				type = 6;

			state = translate[state][type];

			if (state == 7)
				return true;
			else if (state == 8)
				return false;

			s++;
		}
	}
};

解法三:

用多个flag来标识现在的状态, 可读性比较差, 不推荐。

class Solution3 {
public:
    bool isNumber(const char *s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        
        if (s == NULL)
             return false;
             
         while(isspace(*s))
             s++;
             
         if (*s == '+' || *s == '-')
             s++;
             
         bool eAppear = false;
         bool dotAppear = false;
         bool firstPart = false;
         bool secondPart = false;
         bool spaceAppear = false;
         while(*s != '\0')
         {
             if (*s == '.')
             {
                 if (dotAppear || eAppear || spaceAppear)
                     return false;
                 else
                     dotAppear = true;
             }
             else if (*s == 'e' || *s == 'E')
             {
                 if (eAppear || !firstPart || spaceAppear)
                     return false;
                 else
                     eAppear = true;
             }
             else if (isdigit(*s))
             {
                 if (spaceAppear)
                     return false;
                     
                 if (!eAppear)
                     firstPart = true;
                 else
                     secondPart = true;
             }
             else if (*s == '+' || *s == '-')   // behind of e/E
             {
                 if (spaceAppear)
                     return false;
                     
                 if (!eAppear || !(*(s-1) == 'e' || *(s-1) == 'E'))
                     return false;
             }
             else if (isspace(*s))
                 spaceAppear = true;
             else
                 return false;
                 
             s++;            
         }
         
         if (!firstPart) {
             return false;
         }  else if (eAppear && !secondPart) {
             return false;
         } 
         return true;  
    }
};

源码:

Github上的源码

参考:

Leetcode 150题目终结贴 - Valid Number

【leetcode】Valid Number

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/38487239

前言

一直以来看到有好多感兴趣的开源项目托管在github上, 但是因为不懂git, 看的是心痒难搔。断断续续的学习一段时间git, 这个周末算是稍微懂了一点git, 在此做个小结, 也算是方面后面入门的同学们。

关于git学习, 也算是看了好多资料, 有的类似于手册性质的,如《Pro Git》; 有深度剖析原理的, 如何《Git权威指南》 ……  但是这些都不适合尚未入门的同学, 更适合有一定基础的人来看。对于刚接触Git的人来说,更重要的是对Git功能特点有一定的了解, 对Git的操作有一个感性的认识, 再一点点的加深对Git操作的才是高效快速的学习方式。

因此在这对Git高效入门学习进行一个小结。

1. 了解功能特点

要想了解Git的使用, 了解一下Git的功能特点算是一个好的开始。关于这方面推荐两篇文章:

2. 对Git操作有一个感性的认识

使用一下主要的Git命令, 这方面Git官网的一个tutorial做的非常棒!

3. 对GitHub有一个感性认识

尝试着与GitHub进行连接, 创建Repository, Push一个项目。

4. 具体了解TryGit中用到的命令

关于这个, 推荐一个十分棒的图解文章:

5. 未完待续

TODO:

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/33422357

posted in 操作系统 

这几天在学习Linux内核。看赵炯的《LInux内核完全剖析——基于0.12内核》,并试着根据其中的教程先运行一下Linux 0.12。解决了一些问题后,最终得以顺利安装,在此做一下记录。

系统版本: Ubuntu 14.04  32位

仿真器版本:  bochs 2.4.6

  1. 点下面链接下载Linux 0.12相关文件。

Linux-0.12

  1. 配置文件

解压得到的文件 linux-0.12-080324.zip

解压得到的文件夹中有个文件叫 bochsrc-0.12-hd.bxrc  ,在文件最后添加一行

display_library: sdl
  1. 安装bochs相关软件

    sudo apt-get install bochs bochs-x bochs-sdl

安装得到bochs版本是2.4.6

  1. 用bochs运行Linux 0.12

    bochs -f bochsrc-0.12-hd.bxrc

SouthEast

参考:

http://blog.csdn.net/chrisniu1984/article/details/6620722

http://www.cnblogs.com/viviwind/archive/2012/12/21/2827581.html

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/29663091

posted in C/C++ 

不同操作系统,文本文件的行尾符是有区别的。

1. 各系统关于行尾符(End-of-Line)的规定

     Unix每行结尾为"\n",

     Windows系统每行结尾是“\r\n”, 

     Mac OS在 OS X以前每行结尾是"\r", 现在每行结尾是 "\n".

2. 概念区分

中文名 英文名 英文缩写 英文解释 C语言中表示 ASCII码
回车
carriage return CR return \n 0x0a
换行 line feed LF new line \r 0x0d

3. 回车与换行来历

     在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
     于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。
      后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。

     结果是,

      Unix每行结尾为’\n‘, Windows系统每行结尾是“\r\n”,  Mac系统每行结尾是'\r',

     后果是,

     Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;

     Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

4. 编程相关

在Windows系统中,文本文件以"   \r\n"代表换行。

     用fputs等函数写换行符 ' \n'时,Windows会将 ' \n'隐式转换为"\r\n",然后再写入到文件中。

     用fgets等函数读换行符 ' \n' 的时候,Windows会将文件中的"\r\n"隐式转换为'\n',然后再读到变量中。

5. 实例分析 

生成一个包含换行(\n, 0x0A)和回车(\r, 0x0D)组合的文本

     $ echo -en '1\n2\r\n3' > temp

              

十六进制方式查看文本:
     $ xxd temp

       SouthEast
      ![Image 1][]
Linux中查看文本:

     $ xxd -r temp

     $ vim temp
      ![Image 1][] ![SouthEast 1][]

Windows中查看文本:
      ![SouthEast 2][]

6. 不同平台间文本文件转换

**    **编辑器实现转换。

          NotePad++/Ultra Edit/Sublime Text2提供了转换功能。

    用Linux命令实现转换。

         Windows到Unix       \( sed -e 's/.\)//' mydos.txt > myunix.txt

         Unix到Windows       \( sed -e 's/\)/\r/' myunix.txt > mydos.txt

  用Linux命令实现转换。  

$ unix2dos filename 
    $ dos2unix filename

[Image 1]:
[SouthEast 1]: http://img.blog.csdn.net/20140605211633125?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGltYmVyd29sZl8yMDEy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
[SouthEast 2]: http://img.blog.csdn.net/20140605211732968?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGltYmVyd29sZl8yMDEy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

本文章迁移自http://blog.csdn.net/timberwolf_2012/article/details/28687477

/** * RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS. * LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/ /* var disqus_config = function () { this.page.url = PAGE_URL; // Replace PAGE_URL with your page's canonical URL variable this.page.identifier = PAGE_IDENTIFIER; // Replace PAGE_IDENTIFIER with your page's unique identifier variable }; */ (function() { // DON'T EDIT BELOW THIS LINE var d = document, s = d.createElement('script'); s.src = 'https://chenzz.disqus.com/embed.js'; s.setAttribute('data-timestamp', +new Date()); (d.head || d.body).appendChild(s); })();