第一次拼团活动后,多多鸡收到了用户非常不错的反馈。于是,多多鸡又准备举办第二次优惠活动,这次的规则是:买三送一!即每购买3个商品,免费赠送其中价格最低的一个。
皮皮虾现在打算购买 N 个商品(编号 1~N),其中第 i 个商品的价格为 Ai。
现在皮皮虾需要的你帮忙找到一种购买策略,是的能够花费最少的钱买到所有的商品。
输入描述:
共两行,第一行 1 个整数 N,表示皮皮虾准备购买的商品数量。
(1 <= N <= 100,000)
第二行 N 个整数 Ai,分别表示 N 个商品的价格。
(1 <= Ai <= 1,000,000)
输出描述:
共一行,1 个整数,表示皮皮虾购买 N 个物品最少花费多少钱。
示例:
输入:
4
100 200 300 400
输出:
800
说明:
一种可能的方案:分两次购买;
第一次购买价格 200,300,400 的商品,满足买三送一,价格 200 的商品免费赠送,花费:300 + 400 = 700;
第二次购买价格 100,由于不够 3 个商品,无法享受优惠,花费:100
一共花费:700 + 100 = 800。
import java.util.Arrays;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//得到输入
Scanner in = new Scanner(System.in);
int N = in.nextInt(); //第一行,商品个数
int[] A = new int[N];
for(int i = 0; i < N; i++){
A[i] = in.nextInt(); //第二行,商品价格
}
long res = 0; //花钱总和,int不够放,所以改用long
Arrays.sort(A); //价格排序,升序
int times = N/3; //买三送一的次数
for(int i = 0; i < times; i++){
int index = 0;
while(index < 2){ //从后往前累加,去掉赠送的第三个
res += A[N - 3*i - 1 - index];
index++;
}
}
int remain = N % 3; //将不能参与优惠的商品加入
while(remain > 0){
res += A[remain-1];
remain--;
}
System.out.println(res); //打印结果
}
}
将 Arrays.sort() 升序排序改为降序,可以让代码更优美,自定义 compare() 可以参考这位博主的解析:eyckwu: Comparator源码解析
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Test{
public static void main(String[] args) {
//得到输入
Scanner in = new Scanner(System.in);
int N = in.nextInt(); //第一行,商品个数
Integer[] A = new Integer[N];
for(int i = 0; i < N; i++)
A[i] = in.nextInt(); //第二行,商品价格
NumberCompare nCompare = new NumberCompare();
Arrays.sort(A, nCompare); //首先排序,降序
long res = 0; //花钱总和
for(int i = 0; i < N; i++){
if(A[i] % 3 != 2) //余数为2可以优惠
res += A[i];
}
System.out.println(res); //打印结果
}
}
class NumberCompare implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o1 > o2 ? -1 : (o1 == o2 ? 0 : 1);
}
}
leetcode974:和可被K整除的子数组
多多路上从左到右有 N 棵树(编号 1~N),其中第 i 棵树有和谐值 Ai。
多多鸡认为,如果一段连续的树,它们的和谐值之和可以被 M 整除,那么这个区间整体看起来是和谐的。
现在多多鸡想请你帮忙计算以下,满足和谐条件的区间的数量。
输入描述:
第一行,有 2 个整数 N 和 M,表示树的数量以及计算和谐值的参数。
(1 <= N <= 100,000,1 <= M <= 100)
第二行,有 N 个整数 Ai,分别表示第 i 棵树的和谐值。
(0 <= Ai <= 1,000,000,000)
输出描述:
共一行,每行1个整数,表示满足整体是和谐的区间的数量。
示例:
输入:
5 2
1 2 3 4 5
输出:
6
说明:
长度为1:[2], [4]
长度为2:无
长度为3:[1,2,3], [3,4,5]
长度为4:[1,2,3,4], [2,3,4,5]
长度为5:无
共 6 个区间的和谐值之和可以被 2 整除。
备注:
对于 50% 的数据,有 N<=1,000
对于 100%的数据,有 N<=100,00
时间复杂度:O(N2)
空间复杂度:O(N)
时间复杂度过高,达不到要求。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt(); //树数量
int M = in.nextInt(); //M
int[] A = new int[N]; //树的和谐值
for(int i = 0; i < N; i++)
A[i] = in.nextInt();
System.out.println(prefix(A,N,M));
}
//前缀和方法
public static int prefix(int[] a, int n, int m) {
if(n == 0)
return 0;
else {
//构建前缀和数组
int[] sum = new int[n+1];
for(int i = 0; i < n; i++) {
sum[i+1] = sum[i] + a[i];
}
//依次判断余数是否为0
int res = 0; //结果
for(int i = 0; i < n; i++) {
for(int j = i+1; j < n+1; j++) {
if((sum[j] - sum[i]) % m == 0) res++;
}
}
return res;
}
}
}
时间复杂度:O(N)
空间复杂度:O(M)
public int hashTable(int[] a, int n, int m) {
int sum = 0, res = 0;
int[] map = new int[m]; //创建哈希表
map[0] = 1; //重要
for(int i = 1; i <= n; i++) {
sum = sum + a[i-1];
int key = ((sum % m) + m) % m; //防止负数
res += map[key];
map[key]++;
}
return res;
}
未完待续