【秋招机试真题】百度机试0914-2-01字符串

/*
*    题目描述:
*        给出一个长度为n的01串,现在请你找到两个区间,使得这两个
*    区间中0和1的个数相同。
*        两个区间可以相交,但是不可以完全重叠,即两个区间的左右端点
*    不可以完全相同。
*        现在请你找到两个最长的区间,满足以上要求。
*        即假设第一个区间为[s1, t1],区间内有x个0,有y个1,第二个区间
*    为[s2, t2],区间内也要有个x个0和y个1且没有比这两个区间更长的满足
*    这个要求的区间
*    
*    输入描述:
*        输入在一行中给出一个只包含0和1的字符串a。
*        3 < |a| <= 10的6次方
*    输出描述:
*        输出四个整数:s1,t1,s2和t2
*    第一个区间的左右端点编号,以及第二个区间的左右端点编号,字符串从1开始
*    编号。
*    如果有多种满足条件的区间,输出任意两个即可。输入保证答案存在。

*    示例1:
*        输入:
*            11011
*        输出:
*            1 4 2 5
*        说明:
*            第一个区间的串为1101,第二个串为1011,显然第一个串和第二个串包含的0和1的个数相同
*            第二个串包含的0和1的个数相同
*    示例2:
*        输入:
*            101
*        输出:
*            1 2 2 3
*        说明:
*            第一个区间的串为10,第二个区间的串为01,显然包含的0和1的个数相同
*/


说明:百度0914第二题,最后15分钟暴力破解88%,运气还算好


解题思路:

        要寻找两个不完全相同的区间,有同样多的x和y,说明两区间长度相同,所以左端点和右端点一定不相同。判断区间内的x和y的个数是否相同,可以计算两个相同长度区间内的和是否相等来判断。

        1、将字符串中的01字符存储在数组中,并将数组的数字更新为前缀和,比如nums[i]存储前i个数字的和;

        2、暴力破解,固定区间大小,从n-1的大小开始遍历,第一次遇到两个区间和相等,就返回。

 


代码如下:

#include<iostream>
#include<vector>

using namespace std;
vector<int> solution(vector<int>& nums) {
	//
	int n = nums.size();
	int len1, len2; // 记录两个长度
	// 因为要找一个最大的相同的两个区间
	// 所以要从区间为n-1开始遍历,区间为n只有一个区间,不满足两个区间不能完全相同
	// 遇到第一个满足条件的就跳出,返回
	for (int i = n - 1; i > 0; --i) {
		//第一个区间的右端点从[i-1, n-1]
		for (int j = i - 1; j < n; ++j) {
			// 第二个区间的右端点从[j+1, n-1]
			for (int k = j + 1; k < n; ++k) {
				if (j == i - 1) {
					len1 = nums[j];
				}
				else {
					// 求 j-i+1到j区间内的和
					len1 = nums[j] - nums[j - i];
				}
				len2 = nums[k] - nums[k - i];
				if (len1 == len2) return vector<int>{j - i + 2, j+1, k-i+2, k+1};
			}
		}
	}
	return {};
}
int main() {
	string s;
	cin >> s;
	int n = s.size();
	vector<int> nums(n, 0);
	nums[0] = s[0] - '0';
	// 得到数组的前缀和
	// 11011 -> 12234
	for (int i = 1; i < n; ++i) {
		nums[i] = s[i] - '0';
		nums[i] += nums[i - 1];
	}
	vector<int> res = solution(nums);
	for (int i = 0; i < res.size(); ++i) {
		if (i == 0) {
			cout << res[i];
			continue;
		}
		cout << " " << res[i];
		
	}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值