[关闭]
@thousfeet 2018-02-21T20:54:42.000000Z 字数 5316 阅读 1013

来刷题啊 2.21

LeetCode


easy

696. Count Binary Substrings

Give a string s, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively.

Substrings that occur multiple times are counted the number of times they occur.

Example 1:

Input: "00110011"
Output: 6
Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".

Notice that some of these substrings repeat and are counted the number of times they occur.

Also, "00110011" is not a valid substring because all the 0's (and 1's) are not grouped together.

Example 2:

Input: "10101"
Output: 4
Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's.

Note:

s.length will be between 1 and 50,000.
s will only consist of "0" or "1" characters.

【思路】
签到题。求0和1成团粘一起的子串个数,一串里面0和1的数目要相同。
用 s0 存一团里面 0 的个数, s1 存 1 的个数,因为数目要相同,所以每一团里面的可行子串数取较小的那个就好了。

【代码】

  1. int countBinarySubstrings(char* s) {
  2. int count = 0;
  3. int len = strlen(s);
  4. int s0 = 0, s1 = 0;
  5. bool flag = 0;
  6. for(int i = 0; i < len; i++)
  7. {
  8. if(s[i]-'0' == 0)
  9. {
  10. if(flag == 0) s0++;
  11. else
  12. {
  13. count += min(s0,s1);
  14. flag = 0;
  15. s0 = 1;
  16. }
  17. }
  18. else
  19. {
  20. if(flag == 1) s1++;
  21. else
  22. {
  23. count += min(s0,s1);
  24. flag = 1;
  25. s1 = 1;
  26. }
  27. }
  28. }
  29. return count + min(s0,s1);
  30. }

686. Repeated String Match

Given two strings A and B, find the minimum number of times A has to be repeated such that B is a substring of it. If no such solution, return -1.

For example, with A = "abcd" and B = "cdabcdab".

Return 3, because by repeating A three times (“abcdabcdabcd”), B is a substring of it; and B is not a substring of A repeated two times ("abcdabcd").

Note:
The length of A and B will be between 1 and 10000.

打模拟打崩了呀qaq...中间跑去刷了一趟空间回来就过了一个小时了(不x),然后来码了一下打崩掉的思路,突然发现卧槽我打智障了,然后重打十分钟a了...

【思路】
拿 B 的首元素去跟 A 元素一个个比对,如果遇到一个相同的,那说明有希望,就从这里开始往后看能不能一串都匹配上,但是因为可能有多解,所以再继续从 A 的刚刚那里往后找看能不能再遇到一个能匹配上 B 的首元素的,最后取个最小。

【代码】

  1. int repeatedStringMatch(char* A, char* B) {
  2. int lenA = strlen(A);
  3. int lenB = strlen(B);
  4. int res = 10001;
  5. for(int i = 0; i < lenA; i++)
  6. {
  7. if(B[0] == A[i])
  8. {
  9. bool flag = true;
  10. int count = 1;
  11. int beginA = i+1;
  12. for(int j = 1; j < lenB; j++)
  13. {
  14. if(beginA >= lenA)
  15. {
  16. beginA = 0;
  17. count++;
  18. }
  19. if(B[j] != A[beginA++])
  20. {
  21. flag = false;
  22. break;
  23. }
  24. }
  25. if(flag == true) res = min(res,count);
  26. }
  27. }
  28. return res == 10001 ? -1 : res;
  29. }

680. Valid Palindrome II

Given a non-empty string s, you may delete at most one character. Judge whether you can make it a palindrome.

Example 1:

Input: "aba"
Output: True

Example 2:

Input: "abca"
Output: True
Explanation: You could delete the character 'c'.

Note:

The string will only contain lowercase characters a-z. The maximum length of the string is 50000.

【思路】
模拟咯。如果头尾不一样,那就看看如果扔头能匹配上就扔头,扔尾能匹配就扔尾。结果wa掉了扔头扔尾都可以匹配上的情况- -...比如“cuqucu”,所以还要特判一下这种情况,因为这种情况默认是扔头,那就用b1、e1存这时候如果扔尾的始末端,如果扔头失败,那就最后再重判一下扔尾的情况。

【代码】

  1. bool validPalindrome(char* s) {
  2. int len = strlen(s);
  3. bool flag = true;
  4. int count = 0;
  5. int begin = 0, end = len-1;
  6. int b1 = 0,e1 = 0;
  7. while(begin < end)
  8. {
  9. if(s[begin] != s[end])
  10. {
  11. count++;
  12. if(count >= 2)
  13. {
  14. flag = false;
  15. break;
  16. }
  17. if(s[begin+1] == s[end] && s[begin] == s[end-1])
  18. {
  19. b1 = begin;
  20. e1 = end-1;
  21. }
  22. if(s[begin+1] == s[end]) begin++;
  23. else if(s[begin] == s[end-1]) end--;
  24. else flag = false;
  25. }
  26. begin++;
  27. end--;
  28. }
  29. if(b1 < e1 && flag == false)
  30. {
  31. while(b1 < e1) if(s[b1++] != s[e1--]) return false;
  32. flag = true;
  33. }
  34. return flag;
  35. }

【看到的一个优美的递归写法】

  1. class Solution {
  2. public:
  3. bool validPalindrome(string s) {
  4. for (int i = 0, j = s.size() - 1; i < j; i++, j--)
  5. if (s[i] != s[j]) return isp(s, i + 1, j) || isp(s, i, j - 1);
  6. return true;
  7. }
  8. private:
  9. bool isp(string s, int l, int r) {
  10. for (int i = l, j = r; i < j; i++, j--)
  11. if (s[i] != s[j]) return false;
  12. return true;
  13. }
  14. };

medium

767. Reorganize String

Given a string S, check if the letters can be rearranged so that two characters that are adjacent to each other are not the same.

If possible, output any possible result. If not possible, return the empty string.

Example 1:

Input: S = "aab"
Output: "aba"

Example 2:

Input: S = "aaab"
Output: ""

Note:

S will consist of lowercase letters and have length in range [1, 500].

因为要用优先队列不得不用了C++(真tm好用...抱着C语言流下了委屈的泪水)

【思路】
题目要输出字符交换后相同元素不相邻的串。那就要看同个字符的一大串被别的插空能不能插满,只有当某个元素个数太多的时候会出事,比如aaab,里面最多个数的元素 a,最多最多只能跟后面其他的多一个,不然间隔就会插不满(tmp <= len-tmp+1)。
于是先 count 一下每个字母的个数然后全部扔进优先队列,每次取最多的那个来输出,这样一直输 len 个,一旦发现取出来最多的那个不满足之前说的条件( 2*tmp.first > len+1)就GG了,返回空。这里漏考虑的一个点是,未必最多的那个元素扣掉一个之后就会比其他的少,这时候每次取最多就会出事。所以记录一下前一个刚输出的元素 now,如果这次取到的元素前面刚好输的就是它,那就再取下一个次多的来插空(如aaabc)。

【代码】

  1. string reorganizeString(string S) {
  2. int count[26];
  3. memset(count,0,sizeof(count));
  4. int len = S.length();
  5. priority_queue< pair<int, char> > que;
  6. string ans = "";
  7. for(int i = 0; i < len; i++)
  8. count[S[i]-'a']++;
  9. for(int i = 0; i < 26; i++)
  10. if(count[i] != 0) que.push({count[i],i+'a'});
  11. char now = '0';
  12. while(!que.empty())
  13. {
  14. pair<int,char> tmp = que.top();
  15. que.pop();
  16. if(2*tmp.first > len+1) return "";
  17. if(tmp.second == now)
  18. {
  19. pair<int,char> tmp2 = que.top();
  20. que.pop();
  21. now = tmp2.second;
  22. ans += tmp2.second;
  23. tmp2.first--;
  24. len--;
  25. if(tmp2.first != 0) que.push(tmp2);
  26. que.push(tmp);
  27. }
  28. else
  29. {
  30. now = tmp.second;
  31. ans += tmp.second;
  32. tmp.first--;
  33. len--;
  34. if(tmp.first != 0) que.push(tmp);
  35. }
  36. }
  37. return ans;
  38. }

hard

761. Special Binary String

Special binary strings are binary strings with the following two properties:

The number of 0's is equal to the number of 1's.
Every prefix of the binary string has at least as many 1's as 0's.

Given a special string S, a move consists of choosing two consecutive, non-empty, special substrings of S, and swapping them. (Two strings are consecutive if the last character of the first string is exactly one index before the first character of the second string.)

At the end of any number of moves, what is the lexicographically largest resulting string possible?

Example 1:

Input: S = "11011000"
Output: "11100100"
Explanation:
The strings "10" [occuring at S1] and "1100" [at S3] are swapped.
This is the lexicographically largest string possible after some number of swaps.

Note:

S has length at most 50.
S is guaranteed to be a special binary string as defined above.

题意有点懵...英语是真的菜,(没懂为什么example里的 S 会是special..)

直接贴discuss惹:Easy and Concise Solution with Explanation [C++/Java/Python]
可以直接看discuss,讲的很清楚,样例中的 S 在这个解法中会被拆成 1 10 1100 0

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注