题目## 题目
排序
题目难度:简单
知识点:数学逻辑,数组
解题思路:将数组按照从小到大的顺序排序,新旧数组中数值不相同的的总位置数即为题中需要移动的个元素的个数。
方法一
首先创建一个新的数组,使用不断循环的方式将旧数组中的值赋给新的数组,完成数组的复制。然后对新数组进行排序,最后对比两个数组在同一位置处的数值是否相同,统计数值不同的数量。
import java.util.*;
public class Main{
public static void main (String args[]){
Scanner in =new Scanner(System.in);
while (in.hasNext()){
int n=in.nextInt();
int x[]=new int[n];
for (int i=0;i
[题目链接](https://www.nowcoder.com/practice/185dc37412de446bbfff6bd21e4356ec?tpId=182&tqId=25073&sourceUrl=/exam/oj&channelPut=wcsdn&fromPut=wcsdn)
## 解题思路
这是一个完全背包问题的变种,求组合数。关键点:
1. **状态定义**:
- $dp[i]$ 表示组成金额 $i$ 的方案数
2. **状态转移**:
- $dp[i] += dp[i - coin]$
- 对每个面值 $coin$,更新所有可能的金额 $i$
3. **边界条件**:
- $dp[0] = 1$,表示金额为 $0$ 时有 $1$ 种方案(什么都不选)
- 金额为负数时方案数为 $0$
---
## 代码
```cpp []
class Exchange {
public:
int countWays(vector<int>& changes, int n, int x) {
vector<int> dp(x + 1, 0);
dp[0] = 1; // 初始化,金额为0时有1种方案
// 遍历每种面值
for(int coin : changes) {
// 更新所有可能的金额
for(int i = coin; i <= x; i++) {
dp[i] += dp[i - coin];
}
}
return dp[x];
}
};
import java.util.*;
public class Exchange {
public int countWays(int[] changes, int n, int x) {
int[] dp = new int[x + 1];
dp[0] = 1; // 初始化,金额为0时有1种方案
// 遍历每种面值
for(int coin : changes) {
// 更新所有可能的金额
for(int i = coin; i <= x; i++) {
dp[i] += dp[i - coin];
}
}
return dp[x];
}
}
# -*- coding:utf-8 -*-
class Exchange:
def countWays(self, changes, n, x):
dp = [0] * (x + 1)
dp[0] = 1
for coin in changes:
for i in xrange(coin, x + 1):
dp[i] += dp[i - coin]
return dp[x]
算法及复杂度
- 算法:动态规划(完全背包)
- 时间复杂度: O ( n x ) \mathcal{O(nx)} O(nx),其中 n n n 为零钱种类数, x x x 为目标金额
- 空间复杂度: O ( x ) \mathcal{O(x)} O(x),需要一个长度为x+1的dp数组