for (int i = 0; i < 9; i ++) { for (int j = 0; j < 9; j ++) { if (board[i][j] == '.') continue; int b = i / 3 * 3 + j / 3; int no = board[i][j] - '0' - 1; if (row[i][no] || col[j][no] || box[b][no]) returnfalse; row[i][no] = true; col[j][no] = true; box[b][no] = true; } }
returntrue; }
leetcode240 搜索二维矩阵 II
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target
。该矩阵具有以下特性: 每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
利用特性缩小检索范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
boolsearchMatrix(vector<vector<int>>& matrix, int target){ int m = matrix.size(), n = matrix[0].size(); int a = 0, b = 0; int i = m - 1, j = n - 1; while (i >= 0 && j >= 0) { if (matrix[i][j] < target) returnfalse; while (b < n - 1 && matrix[i][b] < target) { b ++; } if (matrix[i][b] == target) returntrue; i --; while (a < m - 1 && matrix[a][j] < target) { a ++; } if (matrix[a][j] == target) returntrue; j --; } returnfalse; }
inttrailingZeroes(int n){ int times = 0; for (int i = 5; i <= n; i += 5) { int count = i; while (count && count % 5 == 0) { times ++; count /= 5; } } return times; }
leetcode201 数字范围按位与
给你两个整数 left 和 right ,表示区间 [left, right]
,返回此区间内所有数字 按位与 的结果(包含 left 、right 端点)。
题解
相邻两个数相与,末尾的 0
将会被消除,通过移位找公共前缀得到区间相与结果
1 2 3 4 5 6 7 8 9 10
intrangeBitwiseAnd(int left, int right){ int shift = 0; // 找到公共前缀 while (left < right) { left >>= 1; right >>= 1; ++shift; } return left << shift; }
classSolution { public: vector<int> productExceptSelf(vector<int>& nums){ vector<int> ret(nums.size()); int mul = nums[0]; ret[0] = 1; for (int i = 1; i < nums.size(); i ++) { ret[i] = mul; mul *= nums[i]; } mul = nums[nums.size() - 1]; for (int i = nums.size() - 2; i >= 0; i --) { ret[i] *= mul; mul *= nums[i]; } return ret; } };
leetcode69 x 的平方根
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5
。
intsingleNumber(vector<int>& nums){ int ret = 0; for (int i = 0; i < 32; i ++) { int count = 0; for (auto n : nums) { count += n >> i & 1; } if (count % 3) ret += 1 << i; } return ret; }
boolcanPartition(vector<int>& nums){ int sum = 0; for (auto n : nums) sum += n; // 若累加值为奇数,则不可能存在这样的两个子集 if (sum % 2 != 0) returnfalse; sum >>= 1; int n = nums.size(); // 判断大小为sum的背包,是否能恰好装入价值为sum的物品 // 其中,各个物品的体积和价值均为nums[i] vector<int> maxPack(sum + 1); for (auto n : nums) { if (n > sum) returnfalse; for (int i = sum; i >= n; i --) { maxPack[i] = max(maxPack[i], maxPack[i - n] + n); } } return maxPack[sum] == sum; }
一维动态规划
leetcode139 单词拆分
给你一个字符串 s 和一个字符串列表 wordDict
作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回
true。
注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
boolwordBreak(string s, vector<string>& wordDict){ vector<bool> dp(s.size() + 1, false); dp[0] = true; for (int i = 1, len = s.size(); i <= len; i ++) { bool flag = false; for (string word : wordDict) { if (i < word.size()) continue; int start = i - word.size(); if (dp[start] && s.substr(start, word.size()) == word) { flag = true; break; } } dp[i] = flag; } return dp[s.size()]; }
牛客 2021360
春招编程题(第一批) 火星人的宝藏
X 星人发现了一个藏宝图,在藏宝图中标注了 N 个宝库的位置。这 N
个宝库连成了一条直线,每个宝库都有若干枚金币。 X
星人决定乘坐热气球去收集金币,热气球每次最多只能飞行 M
千米(假设热气球在飞行过程中并不会发生故障)此外,由于设计上的缺陷,热气球最多只能启动
K 次。 X 星人带着热气球来到了第 1 个宝库(达到第 1
个宝库时热气球尚未启动),收集完第 1
个宝库的金币后将启动热气球前往下一个宝库。如果他决定收集某一个宝库的金币,必须停下热气球,收集完之后再重新启动热气球。当然,X
星人每到一个宝库是一定会拿走这个宝库所有金币的。 已知每一个宝库距离第 1
个宝库的距离(单位:千米)和宝库的金币数量。 请问 X
星人最多可以收集到多少枚金币?
intmain(){ int N, M, K; while (cin >> N >> M >> K) { // 注意 while 处理多个 case vector<vector<int>> ship(N, vector<int>(2, 0)); vector<vector<int>> dp(N, vector<int>(K + 1, 0)); int k, v; for (int i = 0; i < N; i ++) { cin >> k >> v; ship[i][0] = k; ship[i][1] = v; if (i > 0 && k <= M) { dp[i][1] = max(dp[i - 1][1], v); } } if (N - 1 <= K) { longlong ret = 0; for (int i = 1; i < N; i ++) { if (ship[i][0] - ship[i - 1][0] > M) break; ret += ship[i][1]; // cout << ret << endl; } cout << ret + ship[0][1]; return0; } for (int k = 2; k <= K; k ++) { for (int n = k; n < N; n ++) { int nn = n - 1; int maxV = 0; while (nn >= k - 1) { if (dp[nn][k - 1] == 0) { nn --; continue; } if (ship[n][0] - ship[nn][0] > M) break; maxV = max(maxV, dp[nn][k - 1] + ship[n][1]); nn --; } dp[n][k] = maxV; // if (k == K) cout << "n: " << n << " k: " << k << " dp:" << dp[n][k] << endl; } } int ret = 0; for (int i = K; i < N; i ++) { ret = max(ret, dp[i][K]); } cout << ret + ship[0][1]; } return0; } // 64 位输出请用 printf("%lld")
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i
篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h
指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数
是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于
h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。
题解
1 2 3 4 5 6 7 8 9 10
inthIndex(vector<int>& citations){ sort(citations.begin(), citations.end()); int h = 0, i = citations.size() - 1; while (i >= 0 && citations[i] > h) { h++; i--; } return h; }
intlargestRectangleArea(vector<int>& heights){ int maxS = 0; // 方便计算开头与末尾的柱面积 heights.insert(heights.begin(), 0); heights.emplace_back(0); int n = heights.size(); // 单调栈 stack<int> rise; rise.emplace(0); for (int i = 1; i < n; i ++) { // 触及右边界,出栈直到栈再次单调或为空 while (! rise.empty() && heights[rise.top()] > heights[i]) { int h = heights[rise.top()]; rise.pop(); int w = i - rise.top() - 1; maxS = max(maxS, h * w); } rise.emplace(i); } return maxS; }
/** * Your RandomizedSet object will be instantiated and called as such: * RandomizedSet* obj = new RandomizedSet(); * bool param_1 = obj->insert(val); * bool param_2 = obj->remove(val); * int param_3 = obj->getRandom(); */