* [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.