diff --git a/notes/面试总结.md b/notes/面试总结.md new file mode 100644 index 00000000..8519efdd --- /dev/null +++ b/notes/面试总结.md @@ -0,0 +1,126 @@ + +* [1. 字符串组合](#1-字符串组合) +* [2. 实现 Singleton](#2-实现-singleton) +* [3. 数组中重复的数字](#3-数组中重复的数字) + +* [参考文献](#参考文献) + + +# 1. 字符串组合 + +## 题目描述 + +给定三种类型的小球P、Q、R,每种小球的数量分别为np、nq、nr个。现在想讲这些小球排成一条直线,但是不允许相同类型的小球相邻,问有多少种排序方法。 +如若np=2,nq=1,nr=1则共有6种排列方式:PQRP、QPRP、PRQP、PRPQ、RPQP以及PQPR。如果无法组合出合适的结果,则输出0. + +### 输入 +```code +一行以空格相隔的三个数,分别表示为np、nq、nr。 +``` + +### 输出 +```code +排列方法的数量。 +``` + +### 样例输入 +```code +2 1 1 +``` + +### 样例输出 +```code +6 +``` + +## 解题思路 +本题采用一种比较直接的方式进行解题,分为如下步骤: +1. 求解给定P、Q、R个数的时候的全排列,提供`Python`提供的`itertools.permutations`来实现,此时肯定有很多重复。 +2. 去掉重复的情况,通过`Python`提供的`set`来实现。 +3. 通过遍历找出相邻元素重复的串。 +4. 求两个集合的差集,即为答案。 + +```python +import itertools + + +np, nq, nr = [int(k) for k in raw_input().split(" ")] + +count = 0 +result = [] + +for i in itertools.permutations("P"*np + "Q"*nq + "R"*nr,np + nq + nr): + result.append(''.join(i)) + +result_same = [] + +for element in list(set(result)): + for j in range(1, len(element)): + if element[j-1] == element[j]: + result_same.append(element) + +ret_list = list(set(result)^set(result_same)) + +print len(ret_list) +``` + + +# 2. 实现 Singleton + +[单例模式](https://github.com/CyC2018/Interview-Notebook/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) + +# 3. 数组中重复的数字 + +[NowCoder](https://www.nowcoder.com/practice/623a5ac0ea5b4e5f95552655361ae0a8?tpId=13&tqId=11203&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking) + +## 题目描述 + +在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为 7 的数组 {2, 3, 1, 0, 2, 5},那么对应的输出是第一个重复的数字 2。 + +要求复杂度为 O(N) + O(1),也就是时间复杂度 O(N),空间复杂度 O(1)。因此不能使用排序的方法,也不能使用额外的标记数组。牛客网讨论区这一题的首票答案使用 nums[i] + length 来将元素标记,这么做会有加法溢出问题。 + +## 解题思路 + +这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素放到第 i 个位置上。 + +以 (2, 3, 1, 0, 2, 5) 为例: + +```text-html-basic +position-0 : (2,3,1,0,2,5) // 2 <-> 1 + (1,3,2,0,2,5) // 1 <-> 3 + (3,1,2,0,2,5) // 3 <-> 0 + (0,1,2,3,2,5) // already in position +position-1 : (0,1,2,3,2,5) // already in position +position-2 : (0,1,2,3,2,5) // already in position +position-3 : (0,1,2,3,2,5) // already in position +position-4 : (0,1,2,3,2,5) // nums[i] == nums[nums[i]], exit +``` + +遍历到位置 4 时,该位置上的数为 2,但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复。 + +```java +public boolean duplicate(int[] nums, int length, int[] duplication) { + if (nums == null || length <= 0) + return false; + for (int i = 0; i < length; i++) { + while (nums[i] != i) { + if (nums[i] == nums[nums[i]]) { + duplication[0] = nums[i]; + return true; + } + swap(nums, i, nums[i]); + } + } + return false; +} + +private void swap(int[] nums, int i, int j) { + int t = nums[i]; nums[i] = nums[j]; nums[j] = t; +} +``` + + + +# 参考文献 + +- 何海涛. 剑指 Offer[M]. 电子工业出版社, 2012.