- 最大語長積
文字列配列ワードを指定して、length(word [i])* length(word [j])の最大値を求めます。これら2つの語には一般的な文字が含まれていません。各単語は小文字のみを含むと考えることができます。そのような2つの単語がない場合、0が返されます。
比較を容易にするために、ビット演算を実行して各ワードのビットフィールドを格納し、ビット演算によってそれらを互いに比較できます。
class Solution {
public:
int str2int(const string& s) {
int res = 0;
for (auto c : s)
res |= 1 << (c - 'a');
return res;
}
int maxProduct(vector<string>& words) {
int N = words.size();
vector<int> m(N, 0);
for (int i = 0; i < N; ++i)
m[i] = str2int(words[i]);
int res = 0;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < i; ++j) {
if ((m[i] & m[j]) == 0 && words[i].size() * words[j].size() > res)
res = words[i].size() * words[j].size();
}
}
return res;
}
};
- 電球スイッチ
最初は、n個の電球がオフになっています。ラウンド1では、すべての電球をオンにします。2番目のラウンドでは、電球を2つごとにオフにします。第3ラウンドでは、スイッチは3つの電球ごとに切り替えられます(オフの場合はオン、オンの場合はオフ)。iラウンドでは、スイッチはi電球ごとに切り替えられます。n番目のラウンドでは、最後の電球のみを切り替えます。nラウンド後に点灯している電球の数を確認します。
完全な平方数のみが奇数の演算を満たすことができます。問題は1〜n個の完全な平方数、1 * 1、2 * 2、...、\ sqrt {n} * \ sqrt {n}の数を見つけるために進化し、\ sqrtがあります{n} n
class Solution {
public:
int bulbSwitch(int n) {
return sqrt(n);
}
};
- ステッチの最大数
非常に古典的な貪欲なアルゴリズムの問題
class Solution {
public:
// 返回数组nums中,从idx,到nums.size()-len-1中最大数的索引。
int findMaxIndex(vector<int> &nums, int idx, int len){
int maxIdx = idx;
for (int i=idx; i<nums.size()-len; i++){
if (nums[i] > nums[maxIdx]) maxIdx = i;
}
return maxIdx;
}
typedef pair<int,int> P;
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
int n = nums1.size();
int m = nums2.size();
set<P> start; // 存储所有可能的起点索引
start.insert(pair<int,int>{
0,0}); // 数组1初始起点为0,数组2初始起点为0。
vector<int> ans; //存储答案
while(k){
int maxNum = -1;// 第i位数初始值
set<P> temp; // 存储第i位数可以导致的所有可能的起点索引
for(auto p:start){
// 考虑能够到达第i位的所有可能的起点索引
int s1 = p.first;
int s2 = p.second;
int len1 = max(0, k-(m-s2+1));
int maxIdx1 = findMaxIndex(nums1, s1, len1); // 数组1此时能够取的最大数的索引
int maxNum1 = maxIdx1 >= n ? -1 : nums1[maxIdx1];// 该索引对应的最大数
if(maxNum1>=maxNum){
if(maxNum1>maxNum) temp.clear(); // 如果当前起点索引获得的最大数比之前起点索引获得的最大值还要大,那么之前起点索引得到后续可能索引(temp)可以不用考虑。
maxNum = maxNum1;
temp.insert({
maxIdx1+1, s2}); // 更新temp
}
int len2 = max(0, k-(n-s1+1));
int maxIdx2 = findMaxIndex(nums2, s2, len2);
int maxNum2 = maxIdx2 >= m ? -1 : nums2[maxIdx2];
if(maxNum2>=maxNum){
if(maxNum2>maxNum) temp.clear();
maxNum = maxNum2;
temp.insert({
s1, maxIdx2+1});
}
}
ans.push_back(maxNum); // 确定第i位数
start.swap(temp); // 下一位所有可能的起点索引
k--;
}
return ans;
}
};
- 両替
硬貨と異なる金額の硬貨を交換します。合計金額を構成するのに必要なコインの最小数を計算する関数を記述します。コインの組み合わせで合計金額を構成できない場合は、-1を返します。
典型的な貪欲なアルゴリズムの問題、最大の金種が選択されるたびに、リターンが返されない
class Solution {
public:
void coinChange(vector<int>& coins, int amount, int c_index, int count, int& ans)
{
if (amount == 0)
{
ans = min(ans, count);
return;
}
if (c_index == coins.size()) return;
for (int k = amount / coins[c_index]; k >= 0 && k + count < ans; k--)
{
coinChange(coins, amount - k * coins[c_index], c_index + 1, count + k, ans);
}
}
int coinChange(vector<int>& coins, int amount)
{
if (amount == 0) return 0;
sort(coins.rbegin(), coins.rend());
int ans = INT_MAX;
coinChange(coins, amount, 0, 0, ans);
return ans == INT_MAX ? -1 : ans;
}
};
- Swing Sort 2
順序付けられていない配列numsを指定して、nums [0] <nums [1]> nums [2] <nums [3] ...の順序に再配列します。
中央値法を使用して2つの配列に分割し、次にスプライシングを選択します。O(1)空間の複雑さを実現するために、仮想アドレスは、新しい配列を作成する代わりに、元の配列に直接マップされます
class Solution {
public:
void wiggleSort(vector<int>& nums) {
int n = nums.size();
// Find a median.
auto midptr = nums.begin() + n / 2;
nth_element(nums.begin(), midptr, nums.end());
int mid = *midptr;
// Index-rewiring.
#define A(i) nums[(1+2*(i)) % (n|1)]
// 3-way-partition-to-wiggly in O(n) time with O(1) space.
int i = 0, j = 0, k = n - 1;
while (j <= k) {
if (A(j) > mid)
swap(A(i++), A(j++));
else if (A(j) < mid)
swap(A(j), A(k--));
else
j++;
}
}
};
- 3の累乗
整数を指定して、3の累乗かどうかを判別する関数を記述します。
数学の質問、数式
class Solution {
public:
bool isPowerOfThree(int n) {
if(n <= 0) return false;
double a = log10(n) / log10(3) ; //换底
return a == floor(a); //判断换底后的log3n是否为整数,即n是否为3的倍数
}
};
- セクションの数と
、numsに整数の配列を指定すると、lowerとupperで構成される[lower、Upper]間の間隔の数が返されます。
区間合計S(i、j)は、iとjを含む、num内のiからjまでの要素の合計を意味します(i≤j)。
インターバル合計の方法は、以前に何度か登場しました。これは、各位置の合計を0に保存し、減算するだけです。
typedef long long LL;
class Solution {
public:
vector<LL> data;
vector<int> tr;
// 查找小于等于x的第一个数的下标,找不到返回0
int binary_search1(LL x) {
int l = 0, r = data.size() - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (data[mid] <= x) l = mid;
else r = mid - 1;
}
if (l == 0 && data[0] > x) return 0;
else return l + 1;
}
// 查找小于x的第一个数的下标,找不到返回0
int binary_search2(LL x) {
int l = 0, r = data.size() - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (data[mid] < x) l = mid;
else r = mid - 1;
}
if (l == 0 && data[0] >= x) return 0;
else return l + 1;
}
int lowbit(int x) {
return x & -x;
}
int find(int x) {
int ans = 0;
for (int i = x; i; i -= lowbit(i)) ans += tr[i];
return ans;
}
void add(int x, int c) {
int n = tr.size() - 1;
for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
int countRangeSum(vector<int>& nums, int lower, int upper) {
int n = nums.size();
LL sum = 0;
vector<LL> s(n);
for (int i = 0; i < n; i ++) {
sum += nums[i];
s[i] = sum;
}
data = s;
data.push_back(0);
sort(data.begin(), data.end());
data.erase(unique(data.begin(), data.end()), data.end());
tr = vector<int>(data.size() + 1);
// for (int i = 0; i < data.size(); i ++) cout << data[i] << " ";
// cout << endl;
int ans = 0;
int idx_zero = binary_search1(0);
add(idx_zero, 1);
for (auto x : s) {
LL a = x - upper, b = x - lower;
int idxa = binary_search2(a), idxb = binary_search1(b);
int idxx = binary_search1(x);
// cout << idxa << " " << idxb << " " << idxx << endl;
if (idxb != 0) {
if (idxa == 0) ans += find(idxb);
else ans += find(idxb) - find(idxa);
}
add(idxx, 1);
// cout << ans << endl;
}
return ans;
}
};