一周代码合集(Week 4)

LeetCode每日一题

275. H 指数 II

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数,citations 已经按照 升序排列 。计算并返回该研究者的 h 指数。

h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。

请你设计并实现对数时间复杂度的算法解决此问题。

#解题思路和优化思路

这道题和上周末的那道H指数很像 但是他用的是升序数组 无形之中给我们提示 告诉我们需要使用二分法 而最后的要求也明确表示需要用对数时间复杂度的算法结构来解题 所以这道题就是二分套二分 通过二分来加速数组的遍历 加速寻找合适的最大的最小下标 满足大于nums[k]的个数>=k  

#Coding 

class Solution {
    bool check(int k,vector<int>& citations)
    {
        int left=0,right=citations.size()-1;
        while(left<right)
        {
            int mid=(left+right-1)/2;
            if(citations[mid]>=k) right=mid;
            else left=mid+1;
        }
        return citations.size()-left>=k;
    }
public:
    int hIndex(vector<int>& citations) {
        int n=citations.size();
        int left=citations[0],right=citations[n-1];
        while(left<right)
        {
            int mid=(left+right+1)/2;
            if(check(mid,citations)) left=mid;
            else right=mid-1;
        }
        return min(left,n);
    }
};

LeetCode周赛(116双周赛) 

2913. 子数组不同元素数目的平方和 I

给你一个下标从 0 开始的整数数组 nums 。

定义 nums 一个子数组的 不同计数 值如下:

  • 令 nums[i..j] 表示 nums 中所有下标在 i 到 j 范围内的元素构成的子数组(满足 0 <= i <= j < nums.length ),那么我们称子数组 nums[i..j] 中不同值的数目为 nums[i..j] 的不同计数。

请你返回 nums 中所有子数组的 不同计数 的 平方 和。

由于答案可能会很大,请你将它对 109 + 7 取余 后返回。

子数组指的是一个数组里面一段连续 非空 的元素序列。

#解题思路和优化思路

这道题是T1级别的题目 所以直接暴力代码过 暴力的遍历数组 同时从当前遍历下标开始遍历数组 统计不同的数字个数并放入哈希表中 最后令 res 加上 哈希表的size就是答案 

#Coding 

class Solution {
public:
    int sumCounts(vector<int>& nums) {
        int res=0;
        const int mod=1e9+7;
        for(int i=0;i<nums.size();++i)
        {
            unordered_set<int> uset;
            uset.clear();
            for(int j=i;j<nums.size();++j)
            {   
                uset.insert(nums[j]);
                int size=uset.size();
                res=(res+(size*size)%mod)%mod;
            }
        }
        return res;
    }
};

2914. 使二进制字符串变美丽的最少修改次数

给你一个长度为偶数下标从 0 开始的二进制字符串 s 。

如果可以将一个字符串分割成一个或者更多满足以下条件的子字符串,那么我们称这个字符串是 美丽的 :

  • 每个子字符串的长度都是 偶数 。
  • 每个子字符串都  包含 1 或  包含 0 。

你可以将 s 中任一字符改成 0 或者 1 。

请你返回让字符串 s 美丽的 最少 字符修改次数。

#解题思路和优化思路

这道题更像是脑筋急转弯的问题 由于s的长度是偶数 并且每一个子数组串也是偶数 所以他一定是可以被分解完毕而不会剩下余数的 当前问题知道之后 我们就可以设定贪心策略 即 每两个为一组 如果两个不一样 就令 res++ 因为他的子数组串必须是偶数个 即 2 4 6 当子数组的数字个数越多 他需要相同的修改数字就需要更多 所以当每一个数组的数字个数都是2个的时候 就是最优解

#Coding 

class Solution {
public:
    int minChanges(string s) {
        int res=0;
        for(int i=0;i<s.size();i+=2)
        {
            if(s[i]!=s[i+1]) res++;
        }
        return res;
    }
};

2915. 和为目标值的最长子序列的长度

给你一个下标从 0 开始的整数数组 nums 和一个整数 target 。

返回和为 target 的 nums 子序列中,子序列 长度的最大值 。如果不存在和为 target 的子序列,返回 -1 。

子序列 指的是从原数组中删除一些或者不删除任何元素后,剩余元素保持原来的顺序构成的数组。

#解题思路和优化思路

0-1背包问题 很简单的一道题 背包的容量是 target 现在又n个数字 返回可以刚刚好填满背包的最多物品个数 问题转化到这里 就很简单了 套用01背包的板子即可解决问题

#Coding

class Solution {
public:
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        vector<int> dp(target+1,INT_MIN);
        dp[0]=0;
        int s=0;
        for(int i=0;i<nums.size();++i)
        {
            s=min(s+nums[i],target);
            for(int j=s;j>=nums[i];--j)
            {
                dp[j]=max(dp[j],dp[j-nums[i]]+1);
            }
        }
        return dp[target]>0?dp[target]:-1;
    }
};

2916. 子数组不同元素数目的平方和 II

给你一个下标从 0 开始的整数数组 nums 。

定义 nums 一个子数组的 不同计数 值如下:

  • 令 nums[i..j] 表示 nums 中所有下标在 i 到 j 范围内的元素构成的子数组(满足 0 <= i <= j < nums.length ),那么我们称子数组 nums[i..j] 中不同值的数目为 nums[i..j] 的不同计数。

请你返回 nums 中所有子数组的 不同计数 的 平方 和。

由于答案可能会很大,请你将它对 109 + 7 取余 后返回。

子数组指的是一个数组里面一段连续 非空 的元素序列。

#解题思路和优化思路

和T1 是一样的题目 但是时间复杂度需要降低到O(N*logN) 才能实现AC 这里我们引入一个数据结构线段树来优化这道题的时间复杂度 

#Coding

洛谷算法1-2

P1923 【深基9.例4】求第 k 小的数

题目描述

输入 n(1< n < 50000001≤n<5000000 且 n 为奇数)个数字 a_{i}1\leq a_{i}<10^{9}),输出这些数字的第 k 小的数。最小的数是第 0 小。

请尽量不要使用 nth_element 来写本题,因为本题的重点在于练习分治算法

#解题思路和优化思路

这道题我只会使用堆来加速 但是这道题要求的时间复杂度是 O(N) 才能完全AC 所以我只得了60分 这道题通过查看题解 发现需要用到的知识点通过 快排 的使用来加速二分的优化思路 快排的方式就不多叙述了 只讲一下如何利用快排加速算法 利用快排可以将数组分成三个部分 即 小于基准数的 大于基准数的 以及等于基准数的 如果基准数下标小于等于 k 则去大于基准数的地方继续寻找 反之就去小于基准数的地方找 即通过这种方法 不需要遍历整个数组 就可以快速的得到答案  同时学到了快读 对以后的写代码有很大的帮助

#Coding 

#include<bits/stdc++.h>
using namespace std;
vector<long long> nums;
inline int read()
{
	int flag=1,val=0;
	char ch=getchar();
	if(ch>'9' || ch<'0') 
	{
		if(ch=='-') flag=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9')
	{
		val=val*10+(ch-'0');
		ch=getchar();
	}
	return val;
}
int quilkSort(int left,int right)
{
	int mid=nums[left];
	while(left<right)
	{
		while(left<right && nums[right]>=mid) 
		{
			right--;
		}
		nums[left]=nums[right];
		while(left<right && nums[left]<=mid)
		{
			left++;
		}
		nums[right]=nums[left];
	}
	nums[left]=mid;
	return left;
}
void find(int left,int right,int k)
{
	int idx=quilkSort(left,right);
	if(idx==k) 
	{
		cout<<nums[idx];
		exit(0);
	}
	else if(idx>k-1) find(left,idx-1,k);
	else find(idx+1,right,k);
}
int main()
{
	int n=read();
	int k=read(); 
	nums.resize(n);
	for(int i=0;i<n;++i)
	{
		scanf("%d",&nums[i]);
	}
	find(0,n-1,k);
	return 0;
} 

P1271 【深基9.例1】选举学生会

题目描述

学校正在选举学生会成员,有 nn(n\le 999n≤999)名候选人,每名候选人编号分别从 11 到 nn,现在收集到了 mm(m \le 2000000m≤2000000)张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。

#解题思路和优化思路

接下来的两道题就非常的简单 没有什么特别的套路 就是排序数组就好了 调用库函数 sort 来完成算法问题

#Coding 

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,m;
	cin>>n>>m;
	vector<int> nums(m);
	for(int i=0;i<m;++i)
	{
		cin>>nums[i];	
	} 
	sort(nums.begin(),nums.end());
	for(int i=0;i<m;++i)
	{
		if(i) cout<<" ";
		cout<<nums[i];
	}
	return 0;
} 

P1177 【模板】排序

题目描述

将读入的 N 个数从小到大排序后输出。 

 #Coding 

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	vector<int> nums(n);
	for(int i=0;i<n;++i)
	{
		cin>>nums[i];
	}
	sort(nums.begin(),nums.end());
	for(int i=0;i<n;++i)
	{
		if(i) cout<<" ";
		cout<<nums[i];
	} 
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值