分门别类刷leetcode——数组(C++实现)

目录

leetcode 1 两数之和

美团2016真题

不知道是谁家的真题


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){

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值