刷题第三天

189. 旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
示例 2:

输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        k=k%nums.size();
       reverse(nums.begin(),nums.begin()+nums.size()-k);
       reverse(nums.begin()+nums.size()-k,nums.end());
       reverse(nums.begin(),nums.end());
    }
};

268. 丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

进阶:

你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?

示例 1:

输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 2:

输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。
示例 4:

输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

//方法一异或 :把零到n中的所有出现的数字与0-n-1中所有数字相异或
//乘法结合律,每个出现的数字会与0-n-1中的相等数字结合

class Solution {
public:
    int missingNumber(vector<int>& nums) {
            int temp=nums.size();
            for(int i=0;i<nums.size();i++){
                temp^=i^nums[i];
            }
            return temp;
    }
};
//利用和
class Solution {
public:
    int missingNumber(vector<int>& nums) {
            int sum=nums.size();
            for(int i=0;i<nums.size();i++){
                sum+=i;
                sum-=nums[i];
            }
            return sum;
    }
};

136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

class Solution {
public:
    int singleNumber(vector<int>& nums) {
       
       int ret=nums[0];
       for(int i=1;i<nums.size();i++){
           ret^=nums[i];
       }
       return ret;
    }
};

#518. 金币

题目描述
​ 国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续 N 天每天收到 N 枚金币后,骑士会在之后的连续 N+1 天里,每天收到 N+1 枚金币。

​ 现在给出一个日期 x,求第一天到第 x 天骑士总共获得的金币数。

输入
​ 输入一行一个整数 x。(1≤x≤104)

输出
​ 输出骑士总共获得的金币数。

样例输入
10
样例输出
30

//方法一:二分法
#include<iostream>
using namespace std;
int n;
int l, r;
int bs() {
	int l = 1; int r = n;
	while (l != r) {
		int mid = (l + r + 1) / 2;
		int sum = (1 + mid) * mid;
		if (2*n >= sum) {
			l = mid;
		}
		else {
			r = mid - 1;
		}
	}
	return l;
}
int main() {
	int sum = 0;
	cin >> n;
	int day = bs();
	int target = 0;
	int  temp = (1 + day) * day / 2;
	int res = n - temp;
	for (int i = 1; i <= day; i++) {
		target += i * i;
	}
	target += res * (day + 1);
	cout << target << endl;

}
//方法二:o(n)时间复杂度
#include<iostream>
using namespace std;
int main()
{
    int n;
    cin >> n;
    int h=0;
    int l = 1 , i , sum = 0;
    for( i=1;i<=n;i+=l)
    {
        sum+=l*l;
        l++;
        h=i;
    }
    if(i!=n)
    {
        sum+=(n-h)*l;
    }
    cout<<sum;
}

剑指 Offer 56 - I. 数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例 1:

输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:

输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int exor = 0;

        for (int i : nums) {
            exor ^= i; // 求出两个独立数字的异或值
        }

        int first1 = 1;

        while (!(first1 & exor)) {
            first1 <<= 1; // 找到该异或值从右往左第一个 1 出现的位置
        }

        int a = 0, b = 0;

        for (int i : nums) {
            if (i & first1) {
                a ^= i; // 如果 i 从右往左第一个 1 出现的位置与异或值一样
            }
            else {
                b ^= i; // 如果 i 从右往左第一个 1 出现的位置与异或值不一样
            }
        }

        return {a, b};
    }
};

#509. 智力大冲浪

题目描述
​ 小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者 m 元。接下来主持人宣布了比赛规则:

​ 首先,比赛时间分为 n 个时段 (n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限 ti 前完成 (1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费 m 元中扣去一部分钱 wi,wi 为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!

输入
​ 第一行为 m,表示一开始奖励给每位参赛者的钱;

​ 第二行为 n,表示有 n 个小游戏;

​ 第三行有 n 个数,分别表示游戏 1 到 n 的规定完成期限;

​ 第四行有 n 个数,分别表示游戏 1 到 n 不能在规定期限前完成的扣款数。

输出
​ 输出小伟能赢取最多的钱。

样例输入
10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
样例输出
9950

//最小堆加贪心算法
#include<iostream>
using namespace std;
#include<queue>
#include<algorithm>
struct node {
	int time;
	int money;
};
node p[505];
priority_queue<int,vector<int>,greater<int> > que;//最小堆
bool cmp(const node& a, const node& b) {
	return a.time < b.time|| (a.time == b.time && a.money <= b.money);
}
int main() {
	int m,n;
	cin >> m>>n;
	int summoney = 0;
	for (int i = 0; i < n; i++) {
		cin >> p[i].time;
	}
	for (int i = 0; i < n; i++) {
		cin >> p[i].money;
		summoney += p[i].money;
	}
	sort(p, p + n,cmp);
	int sum = 0;
	int t = 1;
	for (int i = 0; i < n; i++) {
		if (p[i].time >= t) {
			que.push(p[i].money);
			t++;
		 }
		else {
			if (p[i].money > que.top()) {
				que.pop();
				que.push(p[i].money);
		   }
		}
		
	}
	while (!que.empty()) {
		sum += que.top();
		que.pop();
	}
	int d = summoney - sum;
	cout << m - d << endl;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值