關於算法與數據結構的相關博文:
一、求字符串的最長無重複字符子串的長度。
解法:動態規劃。優化方案爲:在查找與當前字符相同的字符位置時,可以用一個循環遍歷之前的子串,也可以用hash表直接查找,更省時間。
class Solution {
int lengthOfLongestSubstring(string s) {
int len = s.size(),start = 0;
if (s.empty()||len == 0)
return 0;
int dp[len+1] = {0};
vector<int> hash(256,-1);
for (int i = 0;i < len;i++) {
if (hash[s[i]] >= start)
start = hash[s[i]]+1;
hash[s[i]] = i;
dp[i+1] = max(i-start+1,dp[i]);
}
return dp[len];
}
};
二、字符串轉整數
解法:第一個非空格字符之前的空格忽略;第一個非空格字符是+或-則做相應標記;從第一個非空格字符開始遍歷字符串,遇到數字則按規律疊加起來,遇到非數字字符則停止遍歷。
class Solution
{
public:
int myAtoi(string
str) {
int positive
= 1,i = str.find_first_not_of('
');
long sum
= 0;
if (str[i]
== '+' || str[i] == '-')
positive = str[i++] == '-'?-1:positive;
while (isdigit(str[i]))
{
sum = (sum<<1) + (sum<<3)
+ str[i++]-'0';
if (sum
> INT_MAX)
return positive
== 1?INT_MAX:INT_MIN;
}
return positive*sum;
}
};
解法:
class Solution {public:
bool isPalindrome(int x) {
if (x>0 && x%10 == 0)
return false;
int sum = 0;
while (sum < x) {
sum = (sum<<1)+(sum<<3)+x%10;
x /= 10;
}
if (sum == x||sum/10 == x)
return true;
else
return false;
}
};
解法:二分查找。
①中位數將所有數據分成個數相等的兩個部分,且其中一部分全部大於另一部分;
②同時在兩個有序數組中查找合適的劃分點,由於要保證劃分出的兩部分數據個數相等,所以只在其中一個數組的下標中進行二分搜索劃分點i,從而確定出另外一個數組中的劃分點j;
③爲了確保由i推導出的j>=0,需選擇長度較小的數組進行二分搜索,這樣能確保j合法;
④兩個劃分點左側的數據爲較小的一半,右側爲較大的一半,所以判斷搜索出的劃分點是否合法的條件爲:較小一半的最大值小於較大一半的最小值。否則更新二分搜索的範圍。
class Solution {public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size(),len2 = nums2.size(),half_len = (len1+len2+1)/2;
if (len1 > len2)
return findMedianSortedArrays(nums2,nums1);
int start = 0,end = len1,i,j,numleft,numright;
while(start <= end) {
i = (start+end)/2;
j = half_len-i;
if (i>0&&j<len2&&nums1[i-1] > nums2[j])
end = i-1;
else if (j>0&&i<len1&&nums2[j-1] > nums1[i])
start = i+1;
else {
if (i == 0) {
numleft = nums2[j-1];
}
else if (j == 0) {
numleft = nums1[i-1];
}
else {
numleft = max(nums1[i-1],nums2[j-1]);
}
break;
}
}
if (j == len2 && len1 != 0) numright = nums1[i];
else if (i == len1 && len2 != 0) numright = nums2[j];
else numright = min(nums1[i],nums2[j]);
return (len1+len2)%2 == 1?(double)numleft:(numleft+numright)/2.0;
}
};
五、求字符串的最長迴文子串
解法:遍歷字符串,以每個字符爲中間點向兩邊擴展比較,記錄下最長的迴文子串長度和起始位置即可。遇到連續相同的字符要跳過,他們一定包含在同一個迴文中。
class Solution {public:
string longestPalindrome(string s) {
int len = s.size();
if (len < 2)
return s;
int mid = 0,maxLen = 1,start = 0;
while (mid < len) {
if (len-mid <= maxLen/2)
break;
int left = mid,right = mid;
while (right < len-1 && s[right+1] == s[right])
++right;
mid = right+1;
while (left > 0 && right < len-1 && s[left-1] == s[right+1]) {
--left;
++right;
}
if (right-left+1 > maxLen) {
maxLen = right-left+1;
start = left;
}
}
return s.substr(start,maxLen);
}
};
六、刪除鏈表中某個結點
解法一:循環到鏈表尾,依次將結點值向前複製一步。
class Solution {public:
void deleteNode(ListNode* node) {
while (node->next->next) {
node->val = node->next->val;
node = node->next;
}
node->val = node->next->val;
delete node->next;
node->next = NULL;
}
};
解法二:直接將下一個結點的內容全部複製到當前結點,再刪除下一個結點。
class Solution {public:
void deleteNode(ListNode* node) {
ListNode* next = node->next;
*node = *next;
delete next;
}
};
七、求小於正整數n的素數個數
public:
int countPrimes(int n) {
vector<int> hmap(n,1);
if (n < 3)
return 0;
int upper = sqrt(n);
for (int i = 2;i <= upper;++i) {
if (hmap[i] == 0)
continue;
for (int non_prime = i*i;non_prime < n;) {
hmap[non_prime] = 0;
non_prime += i;
}
}
int count = 0;
for (int k = 2;k < n;++k)
if (hmap[k] == 1)
++count;
return count;
}
};
八、找到二叉樹中所有路徑
注意:題中的""不需要輸出,""只代表字符串。
解法:遞歸。
class Solution {public:
void binaryTreePaths(vector<string>& result, TreeNode* root, string t) {
if (!root->left && !root->right) {
result.push_back(t);
return;
}
if (root->left)
binaryTreePaths(result, root->left, t + "->" + to_string(root->left->val));
if (root->right)
binaryTreePaths(result, root->right, t + "->" + to_string(root->right->val));
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
if (!root) return result;
binaryTreePaths(result, root, to_string(root->val));
return result;
}
};