数据结构刷题日志

我上学期数据结构与算法拿了85分,15分丢在了算法分析设计上面。(思路,代码,分析各五分)其余全部拿到的情况下,只有对基本算法思路全部非常熟悉,才能拿到满分。所以现在开始每天一道题,为后面算法设计打基础

8.21最大容量
题目描述:
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

提示:

n == height.length
2 <= n <= 105
0 <= height[i] <= 104

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:
已知所有的潜在容器壁的高度,使用双指针方法。(我觉得有潜在的贪心算法)开始时,两指针分别指向最左端和最右端,然后将两个指针中较小的那一个向另一侧挪动一位。(这样才有可能找到比当前maxsize更大的容积)

代码实现:

int maxArea(vector<int>& height) {
        int l=0,r=height.size()-1;
        int ans=0;
        while(l<r) {
            int area=(r-l)*min(height[l],height[r]);
            ans=max(ans,area);
            if(height[l]<height[r]) l++;
            else r--;
        }
        return ans;
    }
8.22

【2010统考真题】
算法思想描述:
字符串视为ab,首先将ab分别各自倒置,得a-1b-1,再将a-1b-1整体倒置,得ba
代码:

/*2010年统考真题*/
void reserve(int R[],int from,int to) {//倒置from与to之间的元素 
	int i,temp;
	for(int i=from;i<(to-from+1)/2;i++) 
		swap(R[form+i],R[to-i]); 
}

void converse(int R[],int n,int p){
	reserve(R,0,p-1);
	reserve(R,p,n-1);
	reserve(R,0,n-1);
}

算法分析:(完整版解答)
三个reserve函数的复杂度分别为O(p/2) O((n-p)/2) O(n/2)
时间复杂度O(n)
空间复杂度O(1)

【2011统考真题】
算法设计思想:
由于a,b两序列长度相等,取各自中位数a[m],b[n]进行比较,如果两个中位数相等,则该数为总序列的中位数。如果两中位数不等,则总中位数一定位于现有的两中位数之间。当a[m]>b[n]时,中位数位于a串前半段或b串后半段中,反之亦然。将中位数可能位于的两个半段子串作为新的序列再比较,直到两个中位数相等,即为所求总中位数。
代码描述:
(设计思想有点点问题,我写的是递归实现,由于涉及思想的bug即两中位数不相等,造成无穷递归)下面描述正确的算法思想与代码。

算法设计思想:
分别求A,B的中位数a,b:
若a==b 则a或b为所求中位数
a<b 则舍弃A较小的一半,同时舍弃B较大的一段,并且两次舍弃的长度相等
a>b 则舍弃B较小的一半,同时舍弃A较大的一段
重复以上步骤,直到两个序列中只含一个元素为止
代码描述:(其实我觉得非递归更好,因为没有递归栈,空间复杂度能再低一点)

int M_Search(int a[],int b[],int n) {
	int s1=0,d1=n-1,s2=0,d2=n-1,m1,m2;
	while(s1!=d1||s2!=d2) {
		m1=(s1+d1)/2;
		m2=(s2+d2)/2;
		if(a[m1]==b[m2])
			return a[m1];  //满足条件1
		if(a[m1]<b[m2]) {  //满足条件2 
			if((s1+d1)%2==0) {  //若元素个数为奇数 
				s1=m1;  //舍弃a中间点以前的部分且保留中间点 
				d2=m2;  //舍弃b中间点以后部分且保留中间点 
			} else {
				s1=m1+1;
				d2=m2;
			} 
		} 
		else {
			if((s1+s2)%2==0) {
				d1=m1;
				s2=m2;
			}
			else {
				s1=m1;
				s2=m2+1;
			}
		} 
	}
	return a[s1]<b[s2]?a[s1]:b[s2];
}

8.23
今天看了评分标准,写n2算法可以拿10分,花费大量时间思考最优解是得不偿失的,不应该在这里花费大量时间,于是我打算继续以王道考研书为参考,加快复习步伐,先将所有知识过一遍。先求全面与整体。
【2013统考真题】
标准答案:
算法描述:
从后向前扫描数组元素,标记出一个可能成为主元素的元素num,然后重新计数,确认num是否为主元素。
算法可以分为以下两步:
1.选取候选主元素,依次扫描所给的每个整数,将第一个遇到的整数num保存到c中,记录num的出现次数为1,若遇到下一个整数仍等于num则计数加一,否则计数减一,当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始新一轮计数,重复以上步骤,直到扫描完全部数组元素。
2.判断c中元素是否是真正的主元素。
再次扫描该数组,统计c中元素出现的次数,若大于等于n/2,则为主元素,否则序列中不存在主元素。
算法实现:(我觉得书上写得有点丑)

int majority(int a[],int n) {
	int i,c,count=1;
	c=a[0];
	for(int i=1;i<n;i++) 
		if(a[i]==c) count++;
		else 
			if(count>0) count--;
			else {
				c=a[i];count=1;
			}
		if(count>0)
			for(i=count=0;i<n;i++)
				if(a[i]==c) count++;
			if(count>n/2) return c;
			else return -1;
		
}

显然,时间复杂度O(n),空间复杂度T(1)

当然,如果不这么做自然也可以。
算法描述:将数组进行排序,依次计算每个数字出现的次数,当该次数大于n/2即为所求的主元素
算法设计:

/*当然要用快排啦*/
void qsort(int a[],int l,int r) {  //有点忘记了 
	if(l>r) return;
	int tmp=a[l];
	int i=l;
	int j=r;
	while(i!=j) {
		while(a[j]>=tmp&&j>i) j--;
		while(a[i]<=tmp&&j>i) i++;
		if(j>i) swap(a[i],a[j]);
	}
	a[l]=a[i];
	a[i]=tmp;
	qsort(a,l,i-1);
	qsort(a,i+1,r);
}

int majority(int a[],int n) {
	qsort(a,0,n-1);//排序 
	int c=1;
	int i=0;
	while(i<n) {
		while(a[i]==a[i+1]) {
		c++; i++;
		}
		if(c>n/2) return a[i-1];
		i++;
		c=1;
	}
	return -1;
}

该算法的时间复杂度O(nlogn)空间复杂度O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值