一、奇数位上都是奇数或者偶数位上都是偶数
给定一个长度不小于2的数组arr。 写一个函数调整arr,使arr中要么所有的偶数位上都是偶数,要么所有的奇数位上都是奇数上。 要求:如果数组长度为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1),下标0,2,4,6…算作偶数位,下标1,3,5,7…算作奇数位,例如[1,2,3,4]调整为[2,1,4,3]即可.
对于数组arr而言,偶数个数和奇数个数相同当然为理想情况了,若是偶数个数大于(小于)奇数个数则需要考虑保证偶数(奇数)位上满足条件
- 为了让偶数(奇数)位上的元素满足要求以尾元素为操作空间,从头到尾将元素奇放入尾部进行奇偶性判断然后放入相应位置,直到某一要求达到
class Solution {
public:
/**
* 奇数位上都是奇数或者偶数位上都是偶数
* 输入:数组arr,长度大于2
* len:arr的长度
* 将arr调整成奇数位上都是奇数或者偶数位上都是偶数
*/
void oddInOddEvenInEven(vector<int>& arr, int len) {
int even = 0;
int odd = 1;
int& tail = arr[len - 1];
while(even < len && odd < len)
{
//tail = arr[len - 1];//出错
if((tail & 1) == 0)//出错
{
swap(tail, arr[even]);
even += 2;
}
else{
swap(tail, arr[odd]);
odd += 2;
}
}
}
};
说上两个坑,一个就是
[]和&的优先级问题,在这我先没有带括号,结果导致判断错误,这种错误很难发现,以后的关于&运算不管难不难记得一定要带上括号;另一个就是设定tail时,如果使用tail = arr[len - 1];tail是arr[len - 1]的一份拷贝,这样只会是一种单向赋值即在之后的swap中只会给arr[even]或arr[odd]完成赋值,而实际的arr[len - 1]却并没有完成交换数值的愿望,所以就设定tail为arr[len - 1]的引用
二、淘宝网店
NowCoder在淘宝上开了一家网店。他发现在月份为素数的时候,当月每天能赚1元;否则每天能赚2元。现在给你一段时间区间,请你帮他计算总收益有多少
输入包含多组数据。
每组数据包含两个日期from和to (2000-01-01 ≤ from ≤ to ≤ 2999-12-31)。
日期用三个正整数表示,用空格隔开:year month day
2000 1 1 2000 1 31
2000 2 1 2000 2 29
对应每一组数据,输出在给定的日期范围(包含开始和结束日期)内能赚多少钱
62
29
- 对于输入的每组日期值先看其是不是同年,若同年再看是不是同月。对于同年不同月的要着重考虑起始月和终止月,对于不同年的要着重考虑起始年和终止年,另外还要考虑到是否闰年,是否素数月份的问题
#include <iostream>
#include <vector>
using namespace std;
int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int PrimesMonth[5] = {2, 3, 5, 7, 11};
bool IsLeapYear(int year)
{
if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
return true;
return false;
}
bool IsPrimesMonth(int month)
{
for(int i = 0;i < 5;i++)
{
if(month == PrimesMonth[i])
return true;
}
return false;
}
int main()
{
int yearf,monthf,dayf,yeart,montht,dayt;
vector<int> money;
while(cin >> yearf >> monthf >> dayf >> yeart >> montht >> dayt)
{
int income = 0;
//同年
if(yearf == yeart)
{
int month_money[13] = {0, 62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62 };
if(IsLeapYear(yearf))
{
month_money[2] += 1;
}
//同月
if(monthf == montht)
{
//素数月
if(IsPrimesMonth(monthf))
{
int days = dayt - dayf + 1;
income += days;
}
else//非素数月
{
int days = dayt - dayf + 1;
income += days * 2;
}
}
else//不同月
{
//起始月
if(IsPrimesMonth(monthf))
{
int days = month[monthf] - dayf + 1;
income += days;
}
else//非素数月
{
int days = month[monthf] - dayf + 1;
income += days * 2;
}
for(int m = monthf + 1; m < montht; m++)
{
income += month_money[m];
}
//终止月
if(IsPrimesMonth(montht))
{
int days = dayt - 1 + 1;
income += days;
}
else//非素数月
{
int days = dayt - 1 + 1;
income += days * 2;
}
}
money.push_back(income);
}
else//不同年
{
//第一年
int fmonth_money[13] = {0, 62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62 };
if(IsLeapYear(yearf))
{
fmonth_money[2] += 1;
}
if(IsPrimesMonth(monthf))
{
int days = dayf - 1 + 1;
income += days;
}
else//非素数月
{
int days = dayf - 1 + 1;
income += days * 2;
}
for(int m = monthf + 1; m < 13; m++)
{
income += fmonth_money[m];
}
for(int y = yearf + 1;y < yeart; y++)
{
int month_money[13] = {0, 62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62 };
if(IsLeapYear(y))
{
month_money[2] += 1;
}
for(int m = 1; m < 13; m++)
{
income += month_money[m];
}
}
//最后一年
int Lmonth_money[13] = {0, 62, 28, 31, 60, 31, 60, 31, 62, 60, 62, 30, 62 };
if(IsLeapYear(yeart))
{
Lmonth_money[2] += 1;
}
for(int m = 1; m < montht; m++)
{
income += Lmonth_money[m];
}
if(IsPrimesMonth(montht))
{
int days = dayt - 1 + 1;
income += days;
}
else//非素数月
{
int days = dayt - 1 + 1;
income += days * 2;
}
money.push_back(income);
}
}
for(int i = 0;i < money.size();i++)
{
cout << money[i] << endl;;
}
return 0;
}
在牛客网上跑了下代码,居然卡在98.8%,然后一看是输入
2000 1 12999 12 31出错了,后来想想都笑了,谁家生意能延续上一千年的,就算延续了一千年难道还能一直做每天2块1块的生意吗,所以从现实来说这个代码还是可以的(ps:自我安慰)后来找了下100%的解决方法
#include <iostream>
// 每月天数,不考虑闰年,从 0 开始
inline int day_of_month(int m) {
const static int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
return days[m];
}
// 判断是否是闰年
inline bool leap_year(int y) {
if (y % 4 == 0 && y % 100 != 0) {
return true;
}
if (y % 400 == 0) {
return true;
}
return false;
}
// 一年的收益,不考虑闰年
inline int profit_of_year() {
return 2 * 31
+ 1 * 28
+ 1 * 31
+ 2 * 30
+ 1 * 31
+ 2 * 30
+ 1 * 31
+ 2 * 31
+ 2 * 30
+ 2 * 31
+ 1 * 30
+ 2 * 31;
}
// 判断月份是否是素数,从 0 开始
inline bool prime(int m) {
const static bool p[] = { false, true, true, false, true, false, true, false, false,
false, true, false };
return p[m];
}
int main() {
int year1, month1, day1, year2, month2, day2;
while (std::cin >> year1 >> month1 >> day1 >> year2 >> month2 >> day2)
{
int profit = 0;
int year = year1;
// 计算完整年份的收益
for (int y = year1; y <= year2 - 1; ++y)
{
profit += profit_of_year();
if (leap_year(y))
{
profit += 1;
}
}
// 减去多计算的 year1 从 1月(0) 到 month1 的收益
for (int m = 0; m < month1; ++m)
{
int days;
if (m == month1 - 1) {
// 这个月不完整
days = day1 - 1;
}
else {
days = day_of_month(m);
if (m == 1 && leap_year(year1))
{
days += 1;
}
}
int profit_of_month = days * (prime(m) ? 1 : 2);
profit -= profit_of_month;
}
// 加上少计算的 year2 从 1月(0) 到 month2 的收益
for (int m = 0; m < month2; ++m)
{
int days;
if (m == month2 - 1) {
// 这个月不完整
days = day2;
}
else {
days = day_of_month(m);
if (m == 1 && leap_year(year2))
{
days += 1;
}
}
int profit_of_month = days * (prime(m) ? 1 : 2);
profit += profit_of_month;
}
std::cout << profit << '\n';
}
system("pause");
return 0;
}