#include "stdafx.h" #include "LeetCode_S.h" #include <unordered_map> #include <math.h> #include <stack> using namespace std; CLeetCode_Solution* CLeetCode_Solution::instance = NULL; CLeetCode_Solution::CLeetCode_Solution() { printf("Hello LeetCode "); } CLeetCode_Solution::~CLeetCode_Solution() { } /* 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] */ std::vector<int> CLeetCode_Solution::twoSum(vector<int>& nums, int target) { unordered_map<int, int> m; for (int i = 0; i < nums.size(); i++) { /* *for (int j = i + 1; j < nums.size(); j++) { if (target == (nums[i] + nums[j])) { ret.push_back(i); ret.push_back(j); } }*/ if (m.find(target - nums[i]) != m.end()) { return{ m[target - nums[i]], i }; } m[nums[i]] = i; } return{ 0, 0 }; } /* 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 */ int CLeetCode_Solution::reverse(int x) { int ret(0); while (x != 0) { int pop = x % 10; x /= 10; if (ret > INT_MAX / 10 || (ret == INT_MAX / 10 && pop > 7)) return 0; if (ret < INT_MIN / 10 || (ret == INT_MIN / 10 && pop - 8)) return 0; ret = ret * 10 + pop; } return ret; } /* *判断回文数 **/ bool CLeetCode_Solution::isPalindrome(int x) { if (x < 0) { return false; } long long rst(0); int x_tmp = x; while (x != 0) { int pop = x % 10; rst = rst * 10 + pop; x /= 10; } return (rst == x_tmp); } //二进制相加 std::string CLeetCode_Solution::addBinary(string a, string b) { int al = a.size(); int bl = b.size(); while (al < bl) { a = '0' + a; ++al; } while (bl < al) { b = '0' + b; ++bl; } for (int j = a.size() - 1; j > 0; j--) { a[j] = a[j] - '0' + b[j]; if (a[j] >= '2') { a[j] = (a[j] - '0') % 2 + '0'; a[j - 1] = a[j - 1] + 1; } } a[0] = a[0] - '0' + b[0]; //将ab的第0位相加 if (a[0] >= '2') //若大于等于2,需要进一 { a[0] = (a[0] - '0') % 2 + '0'; a = '1' + a; } return a; }
//罗马数字转阿拉伯数字 int CLeetCode_Solution::romanToInt(string s) { //顺序计算 /* unordered_map<string, int> m; m = { { "I", 1 },{ "IV", 3 },{ "IX", 8 },{ "V", 5 },{ "X", 10 },{ "XL", 30 },{ "XC", 80 },{ "L", 50 },{ "C", 100 },{ "CD", 300 },{ "CM", 800 },{ "D", 500 },{ "M", 1000 } }; int ret = m[s.substr(0, 1)]; for (int i = 1; i < s.size(); i++) { string two = s.substr(i - 1, 2); string one = s.substr(i, 1); ret += m[two] ? m[two] : m[one]; } return ret; */ //倒序计算(速度和内存更佳),从后面往前面取值,每次取一个符号,如果j的值比j+1大时,则ret减去j的值(罗马计算的规则) /* *输入: "LVIII" 输出: 58 解释: L = 50, V= 5, III = 3.*/ unordered_map<char, int> m; m = { { 'I', 1 },{ 'V', 5 },{ 'X', 10 },{ 'L', 50 },{ 'C', 100 },{ 'D', 500 },{ 'M', 1000 } }; int ret = m[s[s.size() - 1]]; for (int j = s.size() - 2; j >= 0; j--) { int numL = m[s[j]]; int numR = m[s[j + 1]]; if (numL >= numR) ret += numL; else ret -= numL; } return ret; }
//字符串数组中的最长公共前缀 std::string CLeetCode_Solution::longestCommonPrefix(vector<string>& strs) { if (0 == strs.size()) return ""; string strfirst = strs[0]; for (int i = 1; i < strs.size(); i++) { int j = 0; for (; j < strfirst.size() && j < strs[i].size(); j++) { if (strfirst[j] != strs[i][j]) break; } strfirst = strfirst.substr(0, j); if (strfirst.empty()) return ""; } return strfirst; }
//判断是否有效的括号 bool CLeetCode_Solution::isValid(string s) { //()[]{} if (s.empty()) return true; if (0 != s.size() % 2) return false; unordered_map<char, char> m = { {'(',')'},{ '[',']' },{ '{','}' } }; stack<char> ret; for (int i = 0; i < s.size(); i++) { if (m.find(s[i])!=m.end()) ret.push(m[s[i]]); else if (ret.empty() || ret.top() != s[i]) return false; else ret.pop(); } if (ret.empty()) return true; else return false; }
//合并两个有序链表 ListNode* CLeetCode_Solution::mergeTwoLists(ListNode* l1, ListNode* l2) { if (l1 == NULL) return l2; if (l2 == NULL) return l1; if (l1->val <= l2->val) { l1->next = mergeTwoLists(l1->next, l2); return l1; } l2->next = mergeTwoLists(l1, l2->next); return l2; }
//删除排序数组中的重复项 int CLeetCode_Solution::removeDuplicates(vector<int>& nums) { /* if (nums.empty()) return 0; int i = 0; for (int j = 1; j < nums.size();++j) { if (nums[j] != nums[i]) { ++i; nums[i] = nums[j]; } } return i + 1;*/ if (nums.empty()) return 0; int val0 = nums[0]; for (vector<int>::iterator iter = nums.begin()+1; iter != nums.end();) { if (val0 == *iter) { iter = nums.erase(iter); } else { val0 = *iter; iter++; } } return nums.size(); } //给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 int CLeetCode_Solution::removeElement(vector<int>& nums, int val) { int len = nums.size(); int pos = 0; while (pos < len) { if (nums[pos] == val) nums[pos] = nums[--len]; else ++pos; } nums.resize(len); return len; }
//手写strstr int CLeetCode_Solution::strStr(string haystack, string needle) { int n = haystack.size(), m = needle.size(); //减少循环,避免越界 for (int i = 0; i < n-m+1; ++i) { int j = 0; for (;j < m; ++j) {
//保证ha一起向前推进 if (haystack[i + j] != needle[j]) break; } if (j == m) return i; } return -1; }
int CLeetCode_Solution::strStr(string haystack, string needle)
{
int n = haystack.size(), m = needle.size();
for (int i = 0; i < n-m+1; ++i)
{
int j = 0;
for (;j < m; ++j)
{
if (haystack[i + j] != needle[j]) break;
}
if (j == m) return i;
}
return -1;
}
//有序vector中插入值
int CLeetCode_Solution::searchInsert(vector<int> &nums, int target)
{
if (nums.size() == 0) return 0;
if (target >= nums[nums.size() - 1]) return nums.size();
int left(0), right(nums.size() - 1);
while (left < right)
{
int mid = left + (right - left) / 2;
if (nums[mid] < target) left = mid + 1;
else right = mid;
}
return left;
}
/*
*「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被读作 "one 1" ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-and-say
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。*/
std::string CLeetCode_Solution::countAndSay(int n)
{
int i = 1;
string ret = "1";
while (i < n)
{
string tmp = "";
int sum = 1;
for (int j = 1; j < ret.size(); ++j)
{
if (ret[j] == ret[j - 1])
{
sum++;
}
else
{
tmp += to_string(sum);
tmp += ret[j - 1];
sum = 1;
}
}
tmp += to_string(sum);
tmp += ret[ret.length() - 1];
ret = tmp;
i++;
}
return ret;
}
//vector<int> v = { -2,1,-3,4,-1,2,1,-5,4 };
int CLeetCode_Solution::maxSubArray(vector<int>& nums)
{
/*
int ret = INT_MIN;
for (int i = 0; i < nums.size(); ++i)
{
int sum_tmp = 0;
for (int j = i; j < nums.size(); ++j)
{
sum_tmp += nums[j];
if (ret < sum_tmp)
{
ret = sum_tmp;
}
}
}
return ret;*/
/*
int ret = INT_MIN;
int sum = 0;
for (int i = 0; i < nums.size(); ++i)
{
sum += nums[i];
ret = max(ret, sum);
if (sum < 0)
{
sum = 0;
}
}
return ret;*/
int sum = 0;
int dp(nums[0]);// 以第i个元素为结尾的一段最大子序和 ,第1个就是第1个前的连续子数组最大值
int ret = dp;
for (int i = 1; i < nums.size(); ++i)
{
dp = max(dp + nums[i], nums[i]);//取dp和 dp+第i个的大值
ret = max(dp, ret);//保持ret是个dp的大值
}
return ret;
}
int CLeetCode_Solution::climbStairs(int n)
{
//上第i个台阶总方法是上第i-1和i-2台阶的和
//比如有3台阶,上第3台阶,可以从第1台阶上或者第二台阶上,上第2台阶
// 可以从第0台阶上,或者第1台阶上,上第一台阶只能从第0台阶上
if (n < 3) return n;
int L1(1), L2(2);//前两个台阶可知数量
int tmp(0);
for (int i = 3; i <= n; ++n)
{
tmp = L1 + L2;
L1 = L2;
L2 = tmp;
}
return tmp;
}
int CLeetCode_Solution::maxProfit(vector<int>& prices)
{
/*
int ret(0);
for (int i = 0; i < prices.size(); ++i)
{
int in_p = prices[i];
for (int j = i+1; j < prices.size();++j)
{
int tmp = prices[j] - in_p;
ret = max(ret, tmp);
}
}
return ret;*/
/*
*
*/
int l_min(prices[0]);//第i天前的买入最小值
int l_max(0);//利润最大值
for (int i = 1; i < prices.size(); ++i)
{
l_max = max(l_max, prices[i] - l_min);
l_min = min(l_min, prices[i]);
}
return l_max;
}
//小偷偷钱,不能偷相邻的两个房子
int CLeetCode_Solution::rob(vector<int>& nums)
{
/*
if (nums.size() == 0) return 0;
vector<int> dp(nums.size()+1);
dp[0] = 0;
dp[1] = nums[0];
for (int i = 2; i <= nums.size(); i++) {
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1]);
}
return dp[nums.size()];
*/
if (nums.size() == 0) return 0;
if (nums.size() == 1) return nums[0];
if (nums.size() == 2) return max(nums[1], nums[0]);
int dp[3] = { 0 };
dp[0] = 0;
dp[1] = nums[0];
for (int i = 2; i < nums.size(); ++i)
{
dp[2] = max(dp[0] + nums[i], dp[1]);
dp[0] = dp[1];
dp[1] = dp[2];
}
return dp[2];
}
//给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次
ListNode* CLeetCode_Solution::deleteDuplicates(ListNode* head)
{
if (head == NULL) return head;
ListNode* tmp = head;
while (tmp->next != NULL)
{
if (tmp->val != tmp->next->val)
{
//往后面走一步
tmp = tmp->next;
}
else
{
//删除掉一个点,保留一个数据
ListNode* tmp1 = tmp->next;
tmp->next = tmp1->next;
delete tmp1;
}
}
return head;
}
void CLeetCode_Solution::merge(vector<int>& nums1, int m, vector<int>& nums2, int n)
{
int m_ = m - 1;
int n_ = n - 1;
int len = m + n - 1;
while (m_ >= 0 && n_ >= 0)
{
nums1[len--] = nums1[m_] > nums2[n_] ? nums1[m_--] : nums2[n_--];
}
while (n_ >= 0) nums1[len--] = nums2[n_--]; //最后 nums2有残留就一定是在最前面的 nums1无所谓,因为已经排好序
}
/*
*输入: 1 1
/ /
2 3 2 3
[1,2,3], [1,2,3]
输出: true
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
**/
bool CLeetCode_Solution::isSameTree(TreeNode* p, TreeNode* q)
{
if (p == NULL && q == NULL) return true;
if (p == NULL || q == NULL) return false;
if (p->val != q->val) return false;
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
/*
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/
2 2
/ /
3 4 4 3
**/
bool isSymmetrictmp(TreeNode* q, TreeNode* p)
{
if (p == NULL && q == NULL) return true;
if (p == NULL || q == NULL) return false;
return (q->val == p->val) && isSymmetrictmp(q->left, p->right) && isSymmetrictmp(q->right, p->left);
}
bool CLeetCode_Solution::isSymmetric(TreeNode* root)
{
if (root == NULL) return true;
//不停的left和right对比就行
return isSymmetrictmp(root->left, root->right);
}
/*
*二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
*/
int CLeetCode_Solution::maxDepth(TreeNode* root)
{
if (root == NULL) return 0;
int ret_L = 1, ret_R = 1;
//取所有left和和right的深度
if (root->left) ret_L += maxDepth(root->left);
if (root->right) ret_R += maxDepth(root->right);
return max(ret_L, ret_R);
}
/*
*给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其自底向上的层次遍历为:
[
[15,7],
[9,20],
[3]
]
*/
vector<vector<int>> ret;
void levelOrderBottomTmp(queue<TreeNode*>current)
{
queue<TreeNode*>next;
vector<int> curVal;
while (!current.empty())
{
TreeNode* top = current.front();
current.pop();
curVal.push_back(top->val);
if (top->left != NULL) next.push(top->left);
if (top->right != NULL) next.push(top->right);
}
if (!next.empty()) (levelOrderBottomTmp(next));
ret.push_back(curVal);
}
vector<vector<int>> CLeetCode_Solution::levelOrderBottom(TreeNode* root) {
if (root == NULL) return ret;
queue<TreeNode*> next;
next.push(root);
levelOrderBottomTmp(next);
return ret;
}