【LeetCode41-50】找出丢失最小正整数,计算蓄水量,检测?*匹配(44),跳跳棋,全排列,矩阵逆转,颠倒字母重新排序(auto,set/multiset,vector初始化),n次方

41.找出丢失的最小正整数

Given [1,2,0] return 3,
and [3,4,-1,1] return 2.

要求用固定大小的空间,以及O(n)


我的解法一:

//添加了辅助项0,后来发现这个方法时间复杂度是O(nlogn),重新做的方法见解法二:

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        nums.push_back(0);//加一项0为了确保为避免【-5,100】这种情况会输出-4
        sort(nums.begin(),nums.end());
        if(nums.size()<1||nums[0]>1)return 1;
        for(int i=1;i<nums.size();++i){
            if(nums[i]-nums[i-1]>1&&nums[i-1]>=0)return nums[i-1]+1;
        }
          return nums[nums.size()-1]+1;  
        }
};


解法二://用到了unordered_map...这下时间复杂度变成了O(n)了…

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        unordered_map<int,int>mapping;
        for(int i=0;i<nums.size();++i){
            mapping[nums[i]]++;
        }
        for(int i=1;i<nums.size()+2;++i){
            if (mapping[i]<1)return i;
        }
        return 1;
        }
};



42.计算蓄水容量

Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

我的解法:【击败了60%】

解决思路:找到最高的板子,那么填满之后肯定是一个不降的序列以及一个不增的序列组成,对应填满即可。

注意,比较大小std::max(t1,t2)   要加上std不然报错……尴尬

class Solution {
public:
    int trap(vector<int>& height) {
        //思路:找到最高的,然后就是标准的先升再降了
        int result=0;
        int max=0,location=0;
        for(int i=0;i<height.size();i++){
            if(height[i]>max){
                max=height[i];
                location=i;
            }
        }
        int begin=0;
        //升序的算一下
        for(int i=0;i<location;++i){
            begin=std::max(height[i],begin);
            if(height[i]<begin)result+=begin-height[i];
        }
        begin=0;
        for(int i=height.size()-1;i>location;--i){
            begin=std::max(height[i],begin);
            if(height[i]<begin)result+=begin-height[i];            
        }
        return result;

    }
};


43.两个字符串表示的数字相乘


规则:长度都小于110,包括0-9,头部不为0,不能直接转为int


我的解法://很单纯地一位一位拆开算了…用了倒置解决了相加的问题,再用加实现了乘……【只击败了0.38%的人】

注意string的倒置的reverse也是要reverse(string.begin(),string.end());

class Solution {
public:
	string multiply(string num1, string num2) {
		string result = "";
		if(num1=="0"||num2=="0")return "0";
		// num2.reverse();
		reverse(num2.begin(), num2.end());//再次强调,reverse是STL里的,不是string的成员函数
		string zero = "";
		for (int i = 0; i<num2.size(); ++i) {
			string temp = multiply2(atoi(num2.substr(i,1).c_str()), num1) + zero;
			result = add(temp, result);
			zero += "0";
		}
		return result;
	}
	string multiply2(int n, string num) {
		string result = "";
		for (int i = 0; i<n; ++i) {
			result = add(result, num);
		}
		return result;
	}
	string add(string num1, string num2) {
		string result = "";
		reverse(num1.begin(), num1.end());
		reverse(num2.begin(), num2.end());
		int max = std::max(num1.size(), num2.size());
		int add = 0, add1 = 0, add2 = 0;
		for (int i = 0; i<max + 1; i++) {
			if (i<num1.size())add1 = atoi(num1.substr(i, 1).c_str()); else add1 = 0;
			if (i<num2.size())add2 = atoi(num2.substr(i, 1).c_str()); else add2 = 0;

			int result1 = (add1 + add2 + add) % 10;
			add = (add1 + add2 + add) / 10;
			if (i != max || (i == max&&result1 == 1))  result += to_string(result1); 


		}
		reverse(result.begin(), result.end());
		return result;
	}
};

别人的不需要reverse的简洁的解法://我还是太耿直了

//用num1[i]-'0'表示大小确实挺方便

//又看了一遍,确实精巧,和我们算乘法反的,但好简洁……

string multiply(string num1, string num2) {
    string sum(num1.size() + num2.size(), '0');
    
    for (int i = num1.size() - 1; 0 <= i; --i) {
        int carry = 0;
        for (int j = num2.size() - 1; 0 <= j; --j) {
            int tmp = (sum[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry;
            sum[i + j + 1] = tmp % 10 + '0';
            carry = tmp / 10;
        }
        sum[i] += carry;
    }
    
    size_t startpos = sum.find_first_not_of("0");
    if (string::npos != startpos) {
        return sum.substr(startpos);
    }
    return "0";
}


44.检测是否匹配(? * 匹配,做了好久,过阵子要在看看,DP搜索肯定方便点)

?可以代表一个字母,*可以代表任意长度的字母

isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

终于做完了……花了好久好久……【击败了75%】


我的做法:把所有*提取出来,再分段检测匹配是否一样…同时要写一个isSame函数检测两个不含有*的string是否匹配

class Solution {
public:
	bool isSame(string s, string p) {
		if (p.size() == 0 && s.size() == 0)return true;
		if (s.size() == p.size()) {
			for (int i = 0; i<s.size(); ++i) {
				if (s[i] == p[i] || p[i] == '?') {}
				else return false;
			}
		}
		else return false;
		return true;
	}

	bool isMatch(string s, string p) {
		vector<int>star;
		for (int i = 0; i<p.size(); ++i) {
			if (p[i] == '*')star.push_back(i);
		}
		if (star.size() == 0)return isSame(s, p);
		int total = s.size() - p.size() + star.size();
		if (total<0)return false;

		bool result = true;
		int begin = 0;


		for (int i = 0; i<star.size() + 1; ++i) {
			string temp = "";
			if (i == 0 && star[i] == 0)++i;

			if (i == 0) { temp = p.substr(0, star[i]); if (isSame(s.substr(0, temp.size()), temp)) { begin = temp.size(); continue; } else return false; }
			else if (i == star.size()) {
				if (star[i - 1] == p.size() - 1)temp = "";
				else
					temp = p.substr(star[i - 1] + 1, p.size() - star[i - 1] - 1);
				if (isSame(s.substr(s.size() - temp.size(), temp.size()), temp) || temp.size() == 0) { return true; }
				else return false;
			}
			else {
				if (i<star.size() - 1 && star[i - 1] + 1 == star[i])continue;
				else
					temp = p.substr(star[i - 1] + 1, star[i] - star[i - 1] - 1);
				temp = p.substr(star[i - 1] + 1, star[i] - star[i - 1] - 1);
			}



			bool temp_result = false;
			int total1 = total;
			for (int ii = begin; ii<begin + total1 + 1; ++ii) {
				if (isSame(s.substr(ii, temp.size()), temp)) { begin = ii + temp.size(); temp_result = true; break; }
				else { --total; }
			}
			if (!temp_result)return false;


		}
		return result;
	}




};

45.跳跳棋

每个int代表下一步可以往后运动的步长,下面这种只击败了0.61%

class Solution {
public:
    int jump(vector<int>& nums) {
        int result=1;
        if(nums.size()==0||nums.size()==1)return 0;
        for(int i=0;i<nums.size();++i){
            nums[i]+=i;
        }
        int begin=0;
        while(nums[begin]<nums.size()-1){
            
            begin=max(nums,begin,nums[begin]);
            result++;
        }
        return result;
        
    }
    int max(vector<int>nums,int begin,int end){
        int result=begin;
        for(int i=begin;i<end+1;++i){
            if(nums[result]<nums[i])result=i;
        }
        return result;
    }

};

46.找出全排列//next_permutations

例如

[1,2,3] have the following permutations:

[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>>result;
        sort(nums.begin(),nums.end());
        if(nums[0]==nums[nums.size()-1]){result.push_back(nums);return result;}//防止【1】这种情况
        int flag=nums[0];int goon=1;
        while(1){
            result.push_back(nums);
            next_permutation(nums.begin(),nums.end());
            if(nums[0]!=flag)goon=0;
            if(nums[0]==flag&&goon==0)break;
        }
        return result;
    }

};


47.返回所有的全排列(这回可能有重复)

//但是我做上一题的时候貌似就包括可能有重复的情况,所有代码和上一题一样就通过了……


class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>>result;
        sort(nums.begin(),nums.end());
        if(nums[0]==nums[nums.size()-1]){result.push_back(nums);return result;}//防止【1】这种情况
        int flag=nums[0];int goon=1;
        while(1){
            result.push_back(nums);
            next_permutation(nums.begin(),nums.end());
            if(nums[0]!=flag)goon=0;
            if(nums[0]==flag&&goon==0)break;
        }
        return result;
    }
};

48.矩阵顺时针旋转90度


class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int size=(matrix.size()+1)/2;
        int length=matrix.size()-1;
        for(int i=0;i<size;++i){
            for(int j=i;j<length-i;++j){
                int temp=matrix[i][j];
                matrix[i][j]=matrix[length-j][i];
                matrix[length-j][i]=matrix[length-i][length-j];
                matrix[length-i][length-j]=matrix[j][length-i];
                matrix[j][length-i]=temp;

            }
        }
        return;
    }
};


49.颠倒字母重新分组 //auto,set/multiset,以及multiset给vector赋值

着重关注,这里用到了用法 auto, set/multiset<类型> , 以及Vector的另一种初始化……利用multiset<string>给vector<string>初始化……

class Solution {
public:
	vector<vector<string>> groupAnagrams(vector<string>& strs) {
		unordered_map<string, multiset<string>>mapping;
		for (int i = 0; i<strs.size(); ++i) {
			string temp = strs[i];
			sort(temp.begin(), temp.end());
			mapping[temp].insert(strs[i]);
		}

		
		vector<vector<string>>result;
		for (auto m : mapping) {
				//这里的返回的是std::pair,第一个代表前面的,第二个代表后面的
			//下面是Vector<类型>的另一种初始化方式  temp(另一个)
			vector<string> temp  (m.second.begin(), m.second.end());
			result.push_back(temp);
		}
		return result;
	}
};

50.计算pow(x,n) //n次方


这里要注意,n可能为负的!!!

class Solution {
public:
	double myPow(double x, int n) {
		if (n == 0) return 1;
		double t = myPow(x, n / 2);
		if (n % 2) {
			return n<0 ? 1 / x*t*t : x*t*t;
		}
		else {
			return t*t;//少计算了一次myPow,碉堡
		}
	}
};


如果用下面这段代码:

class Solution {
public:
	double myPow(double x, int n) {
		if (n == 1 )return x;
		if (n == -1)return 1 / x;
		if(n==0)return 1;
		//二分法
		return myPow(x, n / 2)*myPow(x, n - n / 2);
	}
};

下面的例子会超时间 0.00001 2147483647

所以上面的还是很厉害的……


最近题目做得少了…………



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱铭德

五毛也是爱٩(●´৺`●)૭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值