204 lines
5.6 KiB
Markdown
204 lines
5.6 KiB
Markdown
<!-- GFM-TOC -->
|
||
* [1. 字符串组合](#1-字符串组合)
|
||
* [2. 整数组合求和](#2-整数组合求和)
|
||
* [3. 数组中重复的数字](#3-数组中重复的数字)
|
||
|
||
* [参考文献](#参考文献)
|
||
<!-- GFM-TOC -->
|
||
|
||
# 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. 整数组合求和
|
||
|
||
## 题目描述
|
||
|
||
小米之家是成人糖果店。里面有很多便宜,好用,好玩的产品。中秋节到了,小米之家想给米粉准备一些固定金额大礼包。对于给定的一个金额,需要判断能不能用
|
||
不同种产品(一种产品在礼包最多出现一次)组合出来这个金额。聪明的你来帮帮米家的小伙伴吧。
|
||
|
||
### 输入
|
||
```code
|
||
输入N(N是正整数, N < = 200)
|
||
输入N个价格p(正整数, p <= 10000)用单空格分割
|
||
输入金额M(M是正整数,M <= 100000)
|
||
```
|
||
|
||
### 输出
|
||
```code
|
||
能组合出来输出1
|
||
否则输出0
|
||
```
|
||
|
||
### 样例输入
|
||
```code
|
||
6
|
||
99 199 1999 10000 39 1499
|
||
10238
|
||
```
|
||
|
||
### 样例输出
|
||
```code
|
||
1
|
||
```
|
||
|
||
## 解题思路
|
||
本题采用一种比较直接的方式进行解题,分为如下步骤:
|
||
1. 对输入np进行排序,方便后面快速结束。
|
||
2. 求解给定np时候的0~n个组合的和,提供`Python`提供的`itertools.permutations`来实现。
|
||
3. 如果较小的数相加已经大于目标,可以提前跳出本次循环。
|
||
|
||
|
||
```python
|
||
import itertools
|
||
|
||
n = int(raw_input())
|
||
|
||
|
||
np = [int(k) for k in raw_input().split(" ")]
|
||
np.sort()
|
||
|
||
sum_np = int(raw_input())
|
||
|
||
flag = 0
|
||
|
||
for i in range(n):
|
||
for j in itertools.permutations(np, i):
|
||
if sum(j) > sum_np:
|
||
continue;
|
||
if sum(j) == sum_np:
|
||
flag = 1;
|
||
break;
|
||
|
||
print flag
|
||
```
|
||
|
||
|
||
# 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;
|
||
}
|
||
```
|
||
```python
|
||
nums = [int(k) for k in raw_input().split(" ")]
|
||
print nums
|
||
|
||
def duplicate(nums):
|
||
if len(nums) <= 0:
|
||
return -1, False
|
||
for i in range(len(nums)):
|
||
while nums[i] != i:
|
||
if nums[i] == nums[nums[i]]:
|
||
return nums[i], True
|
||
t = nums[i]
|
||
nums[i] = nums[nums[i]]
|
||
nums[nums[i]] = t
|
||
# nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
|
||
return -1, False
|
||
|
||
print duplicate(nums)
|
||
```
|
||
|
||
|
||
# 参考文献
|
||
|
||
- 何海涛. 剑指 Offer[M]. 电子工业出版社, 2012.
|