目录
leetcode 1 两数之和
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
思路
以数组中的值作为键,以数组中每个数的索引位置作为值,将键值对存入unordered_map中。
对于数组中的每个值,如果在unordered_map中找到了能和他凑齐target且索引位置不同的数时(利用unordered_map的find函数,该函数返回指向找到的键值对的iterator,如果该iterator指向unordered_map的end(),说明没找到对应的值),
如果这两个值的索引位置不同,则返回这两个值在数组中的索引位置。
上代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int>res;
//数组为空,则返回空
if(nums.size()<1) return res;
unordered_map<int, int>num;
//将数组中的值和索引位置存入unordered_map中(因为题目要求不能重复利用这个数组中同样的元素,
//所以不会有重复元素,所以可以放心用map)
for(int i=0; i<nums.size(); i++){
//unordered_map这个关联容器,重载了中括号
//如果中括号中的键在容器中没有,则会创建键值对,将这个键值对存入unordered_map中
//所有的map系的容器都这样,map也这样的
num[nums[i]]= i;
}
//顺序查找数组中的元素,如果找到就返回,所以不用担心i的值会比另一个值的索引位置大
for(int i=0; i<nums.size(); i++){
//如果找到了可以和nums[i]凑成target的值
if(num.find(target-nums[i])!=num.end()){
//如果两个值的索引位置不同,说明没有重复利用同一个元素(题目要求不能重复利用统一元素)
if(i!=num[target-nums[i]]){
res.push_back(i);
res.push_back(num[target-nums[i]]);
return res;
}
}
}
return res;
}
};
美团2016真题
对于一个由0..n的所有数按升序组成的序列,我们要进行一些筛选,每次我们取当前所有数字中从小到大的第奇数位个的数,并将其丢弃。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。
输入描述:
每组数据一行一个数字,为题目中的n(n小于等于1000)。
输出描述:
一行输出最后剩下的数字。
示例1
输入
500
输出
255
思路一:
1、因为是从0开始,所以第一轮移走的是二进制下最右边为0的位置(从0开始的偶数位置)上的数;
2、然后我们发现第二轮各个number的位置等于number/2,即从number位置到number>>1位置(配合下图会更方便观察)
这时候我们依然移走二进制下最右边为0的位置(1(01) 5(101) 9(1001) ……它们第二轮对应的位置是1, 3, 5),最后剩一个数肯定是0到n中二进制下1最多的那个数,因为它每次的位置都是奇数位置。代码如下、
#include <cstdio>
int main() {
int n;
while(scanf("%d", &n) != EOF){
int b = 1;
while(b <= n + 1){
b <<= 1;
}
printf("%d\n", (b >> 1) - 1);
}
return 0;
}
思路二:
* :序列是从 0 到 n-1 的 n 个数, 但是序列的索引是从 1 开始的;
* 假如 n = 10, 那么序列的索引为: 1, 2, 3, ...10;
* 第一次被淘汰掉的索引为: 1, 3, 5,7, 9; 这些索引满足的条件为: index%2 != 0;
* 剩下来的序列索引为: 2, 4, 6, 8, 10; 在这些索引中满足奇数条件: index%4 != 0 的索引为: 2, 6, 10;
* 所以这些索引对应的值将会被在第二轮被淘汰掉;<br>
* 剩下类的索引为: 4, 8;其中满足奇数条件: index%8 !=0 的索引为: 8; 所以最后剩下来的索引就是 8;
* 而索引 8 对应的值为 7, 所以最后剩下来的值为 7.
*
* 由以上推理可以得知, 最后剩下来的那个索引满足条件: index%2^n != 0, 其中 2^n 为小于 n 里面的最大一个.
* 由于索引是从 1 开始的, 而序列的值是从 0 开始的, 所以最后的结果应该为 index - 1
上代码
#include <cstdio>
#include<math.h>
#include<iostream>
using namespace std;
int main() {
int n;
while(scanf("%d", &n) != EOF){
int time=0;
while(n){
n/=2;
time++;
}
cout<<pow(2,time-1)-1<<endl;
}
return 0;
}
不知道是谁家的真题
给定一个数组arr,如果通过调整可以做到arr中任意两个相邻的数字相乘是4的倍数,返回true;如果不能返回false
思路:
对于数组中的数字,可以分成三类
1、偶数但不是4的倍数
2、四的倍数
3、奇数
如果数组中只有2和3,在将两种数穿插排放即可;(即 4奇4奇)
如果数组中有1,2和3,则将1全都放在数组的前半部分,后半部分则摆放2和3的穿插版本。(即 2, 6, 10, 4, 3, 8, 7 这样)
(题不难,我在输入上用了很长时间。如果输入一行数字,以空格隔开,如何吧数字都存入数组中的各个位置呢?可以同getline,然后依次读取输入的这个string类型的变量的每个char,遇到空格则将之前累积的数字存入数组中。写了一波之后发现自己写的只能适用于正整数,如果输入 0 ,则 0 并不能存入数组中,如果是负数呢,如果输入的并不是数字呢。。。。我去,越想越复杂,看一下能实现将一行以空格分开的正整数存入数组中的代码吧)
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main(){
vector<int>nums;
string input;
int temp=0;
while(getline(cin,input)){
for(auto i:input){
if(i>='0'&&i<='9'){
temp=temp*10+(i-'0');
}else{
if(temp){
nums.push_back(temp);
temp=0;
}
}
}
if(temp){
nums.push_back(temp);
temp=0;
}
for(auto i:nums)
cout<<i<<endl;
nums.clear();
}
return 0;
}
功力还是不够啊,上这题的解题代码吧
1 #include<iostream>
2 #include<vector>
3 using namespace std;
4
5 bool calculate(vector<int>&nums){
6 if(nums.size()<1) return false;
7
8 bool res=false;
9 int even_2=0, even_4=0, odd=0;
10 for(auto i :nums){
11 if(i%2==0){
12 if(i%4==0) even_4++;
13 else even_2++;
14 }else
15 odd++;
16 }
17
18 if(even_2==0){
19 if(even_4>=(odd-1))
20 res=true;
21 }else{
22 if(even_4>=odd)
23 res=true;
24 }
25 return res;
26 }
27
28 int main(){
29 vector<int>nums;
30 string input;
31 int temp=0;
32 while(getline(cin,input)){
33 for(auto i:input){
34 if(i>='0'&&i<='9'){
35 temp=temp*10+(i-'0');
36 }else{
37 if(temp){