Skip to content

Latest commit

 

History

History
244 lines (197 loc) · 9.22 KB

LeetCode-01.md

File metadata and controls

244 lines (197 loc) · 9.22 KB

##LeetCode 刷题记录 Easy(一)

##什么是LeetCode?

作为一名本科应届生来讲,面试重点会看重基础,个人的基础算法数据结构,以及语言基础,某些公司还会问一些TCP/IP、组成原理方面的知识。

当然有些人可能会想,做算法,实际工作的时候用得不多呀,但是你也得想,一些语言已经帮我们包装好了一些数据结构和一些模板,比如一些STL等。但是选择合适的数据结构以及算法可以将效率提升很多,选择一个O(n)的算法就是不如选择一个O(lgn)的算法效率高,当然也需要考虑空间复杂度,看情况去用空间换取时间。

尽早的去准备这些东西,可以使得在校招或者面试当中占有一定的优势,毕竟面试里面除了项目的部分,大部分是算法和语言基础,以Java举例,面试官很有可能去问HashMap的底层实现,如果只是知道HashMap的一些peek方法、pop方法、push方法等,而不清楚其底层实现的话,面试就很有可能挂掉。而其底层实现又和数据结构有关,主要和数组和链表有关系,所以问完底层实现以后,可以展开问一些数据结构。然后这一部分基础过关以后,面试官可能会问一些DP,DFS等的一些套路。当这些都满意了以后,就会从一些方向去问一些问题了,比如投的后端就会问一些HTTP协议,投的NLP会问一些基础,投的Java很可能会问GC。

而我们又如何去准备这些基础呢,毕竟大部分大学里并没有ACM的氛围,没有相关的集训队,也没有相关的实验室。而且大部分大学只是去浅显地教数据结构,而不去进行大量的实践,这就会导致学了之后,过段时间就会忘却。所幸的是,ACM有一些OJ平台,可以不断的去练习,实践,国内也有几个出名的OJ,比如POJ,HDOJ,并且好大学都有自己的OJ。而这些OJ对于没有基础的人来说,还是刷起来有点吃力。所以LeetCode定位在为面试者准备的一个OJ,涵盖了一些基础算法,常见数据结构等,应该没有网络流等的一些东西。并且我们可以在这个平台上学到一些东西,一些对边界值的思考,多写一些TestCase。

##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.

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

题解:

通过阅读题目,就是从给定的一个数组里,然后找出可以相加成target这个数的数组下标。

新手很容易写出以下的代码:

	public class Solution {
	    public int[] twoSum(int[] nums, int target) {
	        int[] result = new int[2];
	        for(int i = 0; i < nums.length; i++) {
	            for(int j = i + 1; j < nums.length; j++) {
	                if (nums[i]+nums[j] == target) {
	                    result[0] = i;
	                    result[1] = j;
	                }
	            }
	        }
	        return result;
	    }
	}

当提交之后发现,会提示Your runtime beats 10.32% of java submissions.,为什么只打败那么多呢,思考后会发现,双重for循环以后,会导致时间复杂度的增加。并且好像以前有人说过,能不用双重循环就不用双重循环。

那么这道题是否有其他的思路呢?通过Java的一些集合类可以达到相同的效果吗?

我们是否可以用HashMap去存放相关的数字,去省去一层for循环,也就是以下的代码。

	public class Solution {
	    public int[] twoSum(int[] nums, int target) {
	        HashMap<Integer, Integer> map = new HashMap();
	        for(int i = 0; i < nums.length; i++) {
	            if(map.get(nums[i])!=null) {
	                int[] result = {i, map.get(nums[i])};
	                return result;
	            }
	            map.put(target - nums[i], i);
	        }
	        int[] result = null;
	        return result;
	    }
	}

至此,提交后会得到Your runtime beats 95.65% of java submissions.

并且我们可以从上图可以看到,C的效率是最高的,其次是C++和Golang,而像swift,JavaScript这些语言的效率是比较低的。

##Reverse Integer

Reverse digits of an integer.

Example1: x = 123, return 321 Example2: x = -123, return -321

这道题要逆转数字,属于数学题,有了思路以后不难。主要就是一直取10的余数然后循环。

主要里面好多TestCase需要考虑临界情况,这就使得想起了是用防御式编程呢还是契约式编程。不过实际情况里还是需要考虑到各种情况。

	public class Solution {
	    public int reverse(int x) {
	        int result = 0;
	        while(true) {
				if (result > (Integer.MAX_VALUE / 10)){
					return 0;
				}
				
				if (result < (-Integer.MIN_VALUE / 10)){
					return 0;
				}
	            result = result * 10 + x % 10;
	            x = x / 10;
	            if (x ==0)
	            {
	                break;
	            }
	        }
	        return result;
	    }
	}

##Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space.

这道题,可以通过除法和取余,去对比数字,可以通过逆转数字,然后去判断与原数字是否相同。其负数的情况是直接返回false的。

当然还有很多优化空间或者还有其他的思路。

	public class Solution {
	    public boolean isPalindrome(int x) {
	        int result = 0;
	        int before = x;
	        if (x > 0 && x < 10) {
	            return true;
	        }
	        if (x < 0) {
	            return false;
	        }
	        while(true) {
				if (result > (Integer.MAX_VALUE / 10)){
					return false;
				}
	            result = result * 10 + x % 10;
	            x = x / 10;
	            if (x ==0)
	            {
	                break;
	            }
	        }
	        return before == result;
	    }
	}

##Roman to Integer

罗马数字转数字

Given a roman numeral, convert it to an integer.

Input is guaranteed to be within the range from 1 to 3999.

很常见的逻辑题。

	public class Solution {
	    public int romanToInt(String s) {
	        int result = 0;
	        if (s.length() == 0) {
	            return result;
	        }
	        
	        for (int i = s.length() - 1; i >= 0; i--) {
	            char c = s.charAt(i);
	            switch(c) {
	                case 'I':
	                    if (result >= 5) {
	                        result = result - 1;
	                    } else {
	                        result = result + 1;
	                    }
	                    break;
	                case 'V':
	                    result = result + 5;
	                    break;
	                case 'X':
	                    if (result >= 50) {
	                        result = result - 10;
	                    } else {
	                        result = result + 10;
	                    }
	                    break;
	                case 'L':
	                    result = result + 50;
	                    break;
	                case 'C':
	                    if (result >= 500) {
	                        result = result - 100;
	                    } else {
	                        result = result + 100;
	                    }
	                    break;
	                case 'D':
	                    result = result + 500;
	                    break;
	                case 'M':
	                    result = result + 1000;
	                    break;
	                default:
	            }
	        }
	        
	        return result;
	    }
	}

主要是注意右加左减,在较大的罗马数字的右边记上较小的罗马数字,表示大数字加小数字。

##Longest Common Prefix

Write a function to find the longest common prefix string amongst an array of strings.

输出字符串的公共前缀,字符串的一些操作。其中可以学到了Java如何跳出多重循环。并且也可以学到length()和length的区别。

	public class Solution {
	    public String longestCommonPrefix(String[] strs) {
	        if (strs == null || strs.length == 0) {
	            return "";
	        }
	        
	        if (strs.length == 1) {
	            return strs[0];
	        }
	        
	        String result = "";
	        Label:
	            for(int j = 0; j < strs[0].length(); j++) {
	                for(int i = 1; i < strs.length; i++) {
	                    if (j >= strs[i].length() || strs[i].charAt(j) != strs[0].charAt(j)) {
	                        break Label;
	                    }
	                }
	                result = result + strs[0].charAt(j);
	            }
	        
	        return result;
	    }
	}

##后记

当然代码有点渣,接触leetcode不久,希望可以一块在其中成长,下次写一些链表,栈,字符串等的一些解题记录。并且还有可以从中思考的地方,比如Palindrome Number一题的其他解法,逆转数字可能会导致overflow,这些就留下,需要各位继续思考。以及Longest Common Prefix这题,也可以第0个字符串和其他字符串逐个求前缀。