【数据结构机试复习10】 求和 & 最短前缀

Ex1: 求和:

给定一个具有n个整数的数组,问在S中是否存在3个元素a、b、c使得a + b + c = 0。

注意:三元组(a、b、c)必须是一个非递减顺序(即a<=b<=c)。输出的结果不能重复

例如,给定数组S = [-1 0 1 2 -1 -4],输出[-1, 0, 1]以及[-1, -1, 2]

oj地址:https://leetcode.com/problems/3sum/description/


代码1

先上一个针对Matrix的AC代码(输入输出没有LeetCode严格)

#include<iostream>
#include <set>
#include <algorithm>
using namespace std;

int num[1000050];
set<pair<int, pair<int, int>>> ans;
int main() {
	int n;
	pair<int,pair<int, int>> temp;
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> num[i];
	sort(num, num + n);
	for(int i=0;i<n;i++)
		for(int j=i+1;j<n;j++)
			for (int k = j+1; k < n; k++) {
				temp = make_pair(num[i], make_pair(num[j], num[k]));
				if (num[i] + num[j] + num[k] == 0 && ans.find(temp) == ans.end()) {
					ans.insert(temp);
					printf("%d %d %d\n", num[i], num[j], num[k]);
				}
			}
	return 0;
}

思路:纯暴力,没啥思路

note: 对set、find()、insert等使用仍然不熟练,甚至概念不清


代码2

LeetCode AC代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        int n=nums.size(),left,right;
        sort(nums.begin(),nums.end());  //注意参数
        for(int i=0;i<n-2;i++){
            if(i>0 && nums[i]==nums[i-1]) continue;
            left=i+1,right=n-1;
            while(left<right){
                int sum=nums[i]+nums[right]+nums[left];
                if(sum>0) right--;
                else if(sum<0) left++;
                else{
                    ans.push_back(vector<int>{nums[i],nums[left],nums[right]});
                    while(left+1<right && nums[left+1]==nums[left]) left++;
                    while(right-1>left && nums[right-1]==nums[right]) right--;
                    left++,right--;
                }
            }
        }
        return ans;
    }
};

思路:

首先将数组由小到大排序,使用sort函数,这里我本来写的是sort(num,num+n)在VS上是通过了,可是leetcode上出现了编译错误,还没有研究是什么原因。

i先指向第一个元素,left指向i后一个元素,right指向数组最后一个元素,

然后求得他们的和sum,如果sum比0小,说明元素需要更大一点,所以就让left右移;

反之,如果sum比0大,说明元素需要更小一点,所以就让right左移。

如果sum为0,就将数组nums[i],nums[left],nums[right]}加入ans中,同时将left右移,right左移。

只不过为了避免重复,在左右指针移动的时候要判断下一个指向的元素是不是和之前相同,指针i同理。


Ex2:最短前缀

一个字符串的前缀是从该字符串的第一个字符起始的一个子串。例如“carbon”的前缀是有“c”,“ca”,“car”,“carb”,“carbo”,和“carbon”。空串不是前缀,但是每个非空串是它自身的子串。
我们希望能用前缀来缩略地表示单词。例如“carbohydrate”通常用“carb”来表示。在下面的例子中,“carbohydrate”能被缩写成“carboh”,但是不能被缩写成“carbo”(或其余更短的前缀),因为已经有一个单词用“carbo”开始。
    carbohydrate
    cart
    carbonic
    caribou
    carriage
    car
一个完全匹配会覆盖一个前缀匹配,例如“car”完全匹配单词“car”。因此“car”是“car”的缩略语是没有二义性的,“car”不会被当成“carriage”或者任何在列表中以“car”开始的单词。
现在给你一组单词,要求找到所有单词唯一标识的最短前缀。
输入描述:
输入包含多组数据,每组数据第一行包含一个正整数n(2≤n≤1000)。
紧接着n行单词,单词只有小写字母组成,长度不超过20个字符。
输出描述:
对应每一组数据,按照输入顺序依次输出每个单词的最短前缀。
每组数据之后输出一个空格作为分隔。
示例输入:
3
ab
a
acb
6
carbohydrate
cart
carbonic
caribou
carriage
car


示例输出:
ab
a
ac

carboh
cart
carbon
cari
carr

car

oj地址:http://poj.org/problem?id=2001  (稍有不同)


代码1

针对Matrix可以过

#include <string>
#include <iostream>
using namespace std;

string word[1050];

int  main(){
	int  n;
	bool valid;
	string sub;
	while (cin >> n) {
		for (int i = 0; i < n; i++) cin >> word[i];
		for (int i = 0; i < n; i++) {
			for (int j = 1; j <= word[i].length(); j++) {
				sub = word[i].substr(0, j);
				valid = true;
				for (int k = 0; k < n; k++) {
					if (k != i&&word[k].find(sub) == 0 && j < word[i].length()) {
						valid = false;
						break;
					}
				}
				if (valid) {
					cout << sub << endl;
					break;
				}
			}
		}
		cout << endl;
	}
	return 0;
}
纯暴力,三重循环。

对于每个word,先取前1个字符,看在其余的字符中是否有重复前缀;

若有重复前缀,且当前的sub并非完全匹配,则sub向后扩展一位;

否则就是它的最短前缀。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值