CS-Notes/notes/面试总结.md

127 lines
3.9 KiB
Markdown
Raw Normal View History

<!-- GFM-TOC -->
* [1. 字符串组合](#1-字符串组合)
* [2. 实现 Singleton](#2-实现-singleton)
* [3. 数组中重复的数字](#3-数组中重复的数字)
* [参考文献](#参考文献)
<!-- GFM-TOC -->
# 1. 字符串组合
## 题目描述
给定三种类型的小球P、Q、R每种小球的数量分别为np、nq、nr个。现在想讲这些小球排成一条直线但是不允许相同类型的小球相邻问有多少种排序方法。
如若np=2nq=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.