刷題記錄 -- 筆記文檔

本文记录了作者参与编程竞赛的过程,包括Codeforces、LeetCode等平台的题目,涉及到数组、字符串、回文、二分查找、动态规划等算法问题。文章还分享了刷题经验和优化代码的技巧,如使用哈希表、二分搜索、滑动窗口等方法解决实际问题。
摘要由CSDN通过智能技术生成

Author: 黄建荣
Title: 刷题笔记


  • 开始之前的一些说明
    • 只是刷题记录
    • 所有题目的提交链接,都需要登入到CCF CSP,因为都是模拟考试,需要账号登录的

辅助代码的参考

#pragma GCC POSITION goto

#pragma GCC optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(int argc, char const *argv[]) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
    char *str = (char*)malloc(2 * sizeof(char)); memset(str, 0, sizeof(char)); 
    // char str[32]; memset(str, 0, sizeof(char));
    printf("the size of str: %ld\n", sizeof(str));
    scanf("%2[^abcd]", str); scanf("%*c");
    printf("str = %s\n", str);
    free(str);
    return 0;
}

Codeforce

Educational Codeforces Round 108 (Rated for Div. 2)

問題對應的代碼

A - Red and Blue Beans

具體的題解參考如下

Red and Blue Beans 的相關題解

CCF CSP

2021年12月 赛题

[ 🏚 Question Table CCF CSP ](#Question Table CCF CSP)

第一题 202112-1 序列查询

题目提交链接 这题是真的简单 😄

#pragma GCC POSITION goto

#pragma GCC optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#include <stdio.h>

#define BUFFSIZE (int)10e7

int item[BUFFSIZE], partial_sum[BUFFSIZE];

int main(int argc, const char **argv) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
	int a = 0, n = 0, N = 0, i = 0, _sum= 0;
	scanf("%d%d", &n, &N);scanf("%*c");
	for (i = 0; i < n; ++i) {
		scanf("%d", &a);scanf("%*c");
		item[a]++;
	}
	for (i = 0; i < N - 1; ++i) {
		partial_sum[i + 1] = partial_sum[i] + item[i + 1];
		_sum += partial_sum[i + 1];
	}
	printf("%d", _sum);
	return 0;
}

第二题 序列查询新解

第三题 登机牌条码

第四题 磁盘文件操作

第五题 极差路径

2021年09月 赛题

[ 🏚 Question Table CCF CSP ](#Question Table CCF CSP)

第一题 202109-1 数组推导

题目提交链接 这题是真的简单 😄

#pragma GCC POSITION goto

#pragma GCC optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#include <stdio.h>
#include <string.h>

int main(int argc, const char **argv) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
	int n = 0,  max = 0, min = 0, i = 0, b[100]; 
	memset(b, 0, sizeof(int));
  	scanf("%d", &n);scanf("%*c");
	for(i=0; i<n; ++i) { scanf("%d", &b[i]);scanf("%*c"); }
	max = min = b[0];
	for(i=1; i<n; ++i) {
		max += b[i]; if(b[i]>b[i-1]) min += b[i];
	}
	printf("%d\n%d", max, min);
	return 0;
}

第二题 202109-2 非零段划分

题目提交链接 这题挺复杂的,要那分的话 😢

#pragma GCC POSITION goto

#pragma GCC optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")
#include <stdio.h>

#define N (int)5e5+5
#define M (int)1e4+1
#define _max(a,b) ((a) > (b) ? (a): (b))

int main(int argc, const char **argv) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
    int n = 0, sum = 0, phrase = 0, i = 0, a[N], cnt[N]; // 整数个数,段数
    scanf("%d", &n); scanf("%*c");
    for(i = 1; i <= n; i++) {
        scanf("%d", &a[i]); scanf("%*c");
        if(a[i] > a[i-1]) { //差分,p取a[i-1]+1~a[i]的非零段数量加一
            cnt[a[i-1]+1]++; cnt[a[i]+1]--;
        }
    }
 
    for(i = 1; i < M; i++) {
        sum += cnt[i]; phrase = _max(phrase, sum);
    }
 
    printf("%d\n", phrase);
    return 0;
}

第三题 202109-3 脉冲神经网络

题目提交链接 五味杂陈 😹

注意: 提交测试的时候,如果太多的变量定义在局部栈中,可能会出现栈内存申请不足的情况,最好定义在全局的变量中,虽然让人十分难受,但是现在可能能力不足,无法改善这个问题。

#pragma GCC POSITION goto

#pragma GCC optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#include <stdio.h>
#include <string.h>

#define N  2010
#define INF 1e8
#define _max(a, b) ({(a) > (b) ? (a): (b);})
#define _min(a, b) ({(a) > (b) ? (b): (a);})
#define _rand() ({ _next = _next * 1103515245 + 12345; (unsigned)(_next/65536) % 32768;})
#define add(a,b,c,d) do {e[idx] = (b), W[idx] = (c), D[idx] = (d), ne[idx] = h[(a)], h[(a)] = idx++ ;} while(0)

int n = 0, s = 0, p = 0, T = 0, i = 0, j = 0, k = 0, idx = 0, mod = 0, minc = (int)INF, maxc = (int)-INF, h[N], e[N], D[N], ne[N], r[N], cnt[N];
double dt = 0.0, minv = INF, maxv = -INF, W[N], v[N], u[N], a[N], b[N], c[N], d[N], I[1<<10][N>>1];
static unsigned long _next = 1;

int main(int argc, const char **argv) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
    memset(h, -1, sizeof(h));
    scanf("%d%d%d%d%lf", &n, &s, &p, &T,&dt); scanf("%*c");
    for (i = 0; i < n;) {
        int rn; scanf("%d", &rn); scanf("%*c");
        double vv, uu, aa, bb, cc, dd;
        scanf("%lf%lf%lf%lf%lf%lf", &vv, &uu, &aa, &bb, &cc, &dd); scanf("%*c");
        for (j = 0; j < rn; j++, i++ ) {
            v[i] = vv, u[i] = uu, a[i] = aa, b[i] = bb, c[i] = cc, d[i] = dd;
        }
    }

    for (i = n; i < n + p; i++ ) {scanf("%d", &r[i]); scanf("%*c");}

    while (s--) {
        int a = 0, b = 0, d = 0;
        double c;
        scanf("%d%d%lf%d", &a, &b, &c, &d); scanf("%*c");
        add(a, b, c, d);
        mod = _max(mod, d + 1);
    }

    for (i = 0; i < T; i++ ) {
        int t = i % mod;
        for (j = n; j < n + p; j++ )
            if (r[j] > _rand()) {
                for (k = h[j]; ~k; k = ne[k]) {
                    int x = e[k];
                    I[(t + D[k]) % mod][x] += W[k];
                }
            }

        for (j = 0; j < n; j++ ) {
            double vv = v[j], uu = u[j];
            v[j] = vv + dt * (0.04 * vv * vv + 5 * vv + 140 - uu) + I[t][j];
            u[j] = uu + dt * a[j] * (b[j] * vv - uu);

            if (v[j] >= 30) {
                for (k = h[j]; ~k; k = ne[k]) {
                    int x = e[k];
                    I[(t + D[k]) % mod][x] += W[k];
                }
                cnt[j]++ ;
                v[j] = c[j], u[j] += d[j];
            }
        }
        memset(I[t], 0, sizeof(I[t]));
    }

    for (i = 0; i < n; i++ ) {
        minv = _min(minv, v[i]);
        maxv = _max(maxv, v[i]);
        minc = _min(minc, cnt[i]);
        maxc = _max(maxc, cnt[i]);
    }

    printf("%.3lf %.3lf\n", minv, maxv); printf("%d %d\n", minc, maxc);
    return 0;
}

第四题 202109-4 收集卡牌

题目提交链接 😂

#pragma GCC POSITION goto

#pragma GCC optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#include <stdio.h>

#define N 16

double dp[1<<N][N*N], p[N];
int main(int argc, const char **argv) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
    int n = 0, k = 0, i = 0, j = 0, l = 0; scanf("%d%d", &n, &k); scanf("%*c");
    for(i=0; i<n; i++) { scanf("%lf", &p[i]); scanf("%*c"); }
    dp[(1<<n)-1][0] = 0;
    for(i = (1<<n)-2; i > -1; i--){
    	for(j = k*n; j > -1; j--) {
	    	for(l = 0; l < n; l++) {
	    		if((i >> l) & 1) dp[i][j] += dp[i][j+1] * p[l];
	    		else dp[i][j] += dp[i | (1 << l)][j] * p[l];
			}
			dp[i][j] += 1;
			int cnt = n;
			for(l = 0; l < n; l++) if((i >> l) & 1) cnt--;
			if(j >= (cnt * k)) dp[i][j] = 0;
		}
	}
    printf("%.10lf\n",dp[0][0]);
	return 0;
}

第五题 202109-5 箱根山岳险天下

题目提交链接 😢 难,真的太难了 😢

为什么这题 宏函数 会出现 Segmention fault

#pragma G++ POSITION goto

#pragma G++ optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>

#define maxn (int)3e5+10
#define ls ch[x][0]
#define rs ch[x][1]

#define getch(x) ({ch[fa[x]][1] == x;})
#define isRoot(x) ({ch[fa[x]][0] != x && ch[fa[x]][1] != x;})
#define _swap(a,b) do {\
    void* _tmp = malloc(sizeof((a)));\
    memcpy(_tmp, &a, sizeof(a)); (a) = (b); memcpy(&b, _tmp, sizeof(a));\
    free(_tmp);\
} while(0)
#define pushdownRev(x) do { _swap(ls, rs); lazy_rev[(x)] ^= 1; } while(0)
#define pushdownMul(x,v) do {\
    val[(x)] = ( val[(x)] * (v) ) % mod;\
    sum[(x)] = (sum[(x)] * (v)) % mod;\
    lazy_mul[(x)] = (lazy_mul[(x)] * (v)) % mod;\
} while(0)
#define pushdown(x) do {\
    if (lazy_rev[(x)]) {\
        if (ls) pushdownRev(ls);\
        if (rs) pushdownRev(rs);\
        lazy_rev[(x)] ^= 1;\
    }\
    if (lazy_mul[(x)] != 1) {\
        if (ls) pushdownMul(ls, lazy_mul[(x)]);\
        if (rs) pushdownMul(rs, lazy_mul[(x)]);\
        lazy_mul[x] = 1;\
    }\
} while(0)

#define pushup(x) do { sum[(x)] = (sum[ls] + sum[rs] + val[(x)]) % mod; } while(0)

#define rotate(x) do {\
    int _y = fa[(x)], _z = fa[_y], _chk = getch((x)), _w = ch[(x)][_chk ^ 1];\
    if (!isRoot(_y)) ch[_z][getch(_y)] = (x);\
    ch[(x)][_chk ^ 1] = _y;\
    ch[_y][_chk] = _w;\
    if (_w) fa[_w] = _y;\
    fa[_y] = (x), fa[(x)] = _z;\
    pushup(_y);\
} while(0)

#define splay(x) do {\
    int _top = 0, _y = (x);\
    st[++_top] = _y;\
    while (!isRoot(_y)) {\
        _y = fa[_y];\
        st[++_top] = _y;\
    }\
    while (_top) pushdown(st[_top--]);\
    while (!isRoot((x))) {\
        _y = fa[(x)];\
        if (!isRoot(_y)) rotate(getch((x)) == getch(_y) ? _y : (x));\
        rotate(x);\
    }\
    pushup((x));\
} while(0)

#define access(x) do {\
    int _y = 0;\
    for (_y = 0; (x); (x) = fa[_y = (x)]) {\
        splay(x);\
        rs = _y;\
        pushup((x));\
    }\
} while(0)

#define makeRoot(x) do {\
    access((x));\
    splay((x));\
    pushdownRev((x));\
} while(0)

#define split(x,y) do {\
    makeRoot((x));\
    access((y));\
    splay((y));\
} while(0)

#define link(x,y) do {\
    makeRoot((x));\
    fa[(x)] = (y);\
} while(0);

#define insertPlayer(day,v) do {\
    ++tot;\
    player[tot] = {(day), (cur)};\
    ranklist[cur_rank].push_back(tot);\
    val[tot] = sum[tot] = (v);\
    lazy_mul[tot] = 1;\
    lazy_rev[tot] = 0;\
    if (cur) link(tot, cur);\
    cur = tot;\
} while(0)

#define findPlayer(_day,rk) ({\
    int _l = 0, _r = ranklist[(rk)].size() - 1, _mid = 0, _ans = 0;\
    while (_l <= _r) {\
        _mid = (_l + _r) >> 1;\
        if (player[ranklist[(rk)][(_mid)]].day <= (_day)) {\
            _ans = _mid;\
            _l = _mid + 1;\
        } else {\
            _r = _mid - 1;\
        }\
    }\
    ranklist[(rk)][_ans];\
})


struct {int day, fa;} player[maxn];


int m = 0, T = 0, cur = 0, cur_rank = 0, tot = 0, opt = 0, s = 0, l = 0, r = 0, x = 0, y = 0, A = 0, st[maxn], ch[maxn][2], fa[maxn], lazy_rev[maxn];
long long mod = 0, val[maxn], sum[maxn], lazy_mul[maxn];
std::vector<int> ranklist[maxn];

int main(int argc, const char **argv) {
    TODO(這題是錯的,代碼不能通過,會出現Segmentation fault)
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
    scanf("%d%lld%d", &m, &mod, &T); scanf("%*c");
    for (int day = 1; day <= m; ++day) {
        scanf("%d", &opt); scanf("%*c");
        if (opt == 1) {
            scanf("%d", &x); scanf("%*c");
            if (T == 1)
                x ^= A;
            if (x == 0) {
                cur = player[cur].fa;
                --cur_rank;
            } else {
                insertPlayer(day, x);
            }
        } else if (opt == 2) {
            scanf("%d%d%d%d", &s, &l, &r, &y); scanf("%*c");
            if (T == 1)
                y ^= A;
            l = findPlayer(s, l);
            r = findPlayer(s, r);
            split(l, r);
            pushdownMul(r, y);
        } else {
            scanf("%d%d%d", &s, &l, &r); scanf("%*c");
            l = findPlayer(s, l);
            r = findPlayer(s, r);
            split(l, r);
            A = sum[r];
            printf("%d\n", A);
        }
    }
}

参考的代码

#pragma G++ POSITION goto

#pragma G++ optimize(2)

// #pragma GCC optimize(3,"Ofast","inline")

#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>

#define maxn (int)3e5+10

struct { int day, fa; } player[maxn];
int m = 0, T = 0, cur = 0, cur_rank = 0, tot = 0, opt = 0, s = 0, l = 0, r = 0, x = 0, y = 0, A = 0,
    st[maxn], ch[maxn][2], fa[maxn], lazy_rev[maxn];
long long mod = 0, val[maxn], sum[maxn], lazy_mul[maxn];
std::vector<int> ranklist[maxn];

#define getch(x) ({ch[fa[(x)]][1] == (x);})
#define isRoot(x) ({ch[fa[(x)]][0] != (x) && ch[fa[(x)]][1] != (x);})
#define swap(a,b) do {(a) ^= (b) ^= (a) ^= (b); } while(0)

void pushdownRev(int x) {
    // 执行翻转操作
    swap(ch[x][0], ch[x][1]);
    lazy_rev[x] ^= 1;
}
void pushdownMul(int x, long long v) {
    // 执行区间乘操作
    val[x] = (val[x] * v) % mod;
    sum[x] = (sum[x] * v) % mod;
    lazy_mul[x] = (lazy_mul[x] * v) % mod;
}
void pushdown(int x) {
    // 下传懒惰标记
    if (lazy_rev[x]) {
        if (ch[x][0]) pushdownRev(ch[x][0]);
        if (ch[x][1]) pushdownRev(ch[x][1]);
        lazy_rev[x] ^= 1;
    }
    if (lazy_mul[x] != 1) {
        if (ch[x][0]) pushdownMul(ch[x][0], lazy_mul[x]);
        if (ch[x][1]) pushdownMul(ch[x][1], lazy_mul[x]);
        lazy_mul[x] = 1;
    }
}
void pushup(int x) {
    // 更新状态 (maintain)
    sum[x] = (sum[ch[x][0]] + sum[ch[x][1]] + val[x]) % mod;
}
void rotate(int x) {
    // splay 旋转操作
    int y = fa[x], z = fa[y], chk = getch(x), w = ch[x][chk ^ 1];
    if (!isRoot(y)) ch[z][getch(y)] = x;
    ch[x][chk ^ 1] = y; ch[y][chk] = w;
    if (w) fa[w] = y;
    fa[y] = x, fa[x] = z;
    pushup(y);
}
void splay(int x) {
    // 将目前结点旋转到所在 splay 的根
    int top = 0, y = x;
    st[++top] = y;
    while (!isRoot(y)) {
        y = fa[y]; st[++top] = y;
    }
    while (top) pushdown(st[top--]);
    while (!isRoot(x)) {
        y = fa[x];
        if (!isRoot(y)) rotate(getch(x) == getch(y) ? y : x);
        rotate(x);
    }
    pushup(x);
}
void access(int x) {
    // 开辟一条只含有原树的根到 x 的路径结点的实链
    for (int y = 0; x; x = fa[y = x]) {
        splay(x);
        ch[x][1] = y;
        pushup(x);
    }
}
void makeRoot(int x) {
    // 让 x 称为原树的根
    access(x);  splay(x); pushdownRev(x);
}
void split(int x, int y) {
    // 开辟一条只含有 x 到 y 路径结点的实链,y 为 splay 的根
    makeRoot(x); access(y); splay(y);
}
void link(int x, int y) {
    // 连接两个部分
    makeRoot(x); fa[x] = y;
}
void insertPlayer(int day, long long v) {
    // 加入新队员
    ++tot;
    // 对原树进行操作
    player[tot] = { day, cur };
    ++cur_rank;
    ranklist[cur_rank].push_back(tot);
    // 对辅助树进行操作
    val[tot] = sum[tot] = v;
    lazy_mul[tot] = 1;
    lazy_rev[tot] = 0;
    // 如果目前队伍有人,则加入队伍
    if (cur) link(tot, cur);
    cur = tot;
}
int findPlayer(int day, int rk) {
    // 查找在第 day 天排名 rk 的队员编号
    int l = 0, r = ranklist[rk].size() - 1, mid, ans = 0;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (player[ranklist[rk][mid]].day <= day) {
            ans = mid; l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    return ranklist[rk][ans];
}


int main(int argc, const char **argv) {
#ifndef ONLINE_DEBUG
    freopen("input.data", "r", stdin);
    freopen("output.data", "w", stdout);
#endif
    scanf("%d%lld%d", &m, &mod, &T); scanf("%*c");
    for (int day = 1; day <= m; ++day) {
        scanf("%d", &opt); scanf("%*c");
        if (opt == 1) {
            scanf("%d", &x); scanf("%*c");
            if (T == 1) x ^= A;
            if (x == 0) {
                cur = player[cur].fa; --cur_rank;
            } else insertPlayer(day, x);
        } else if (opt == 2) {
            scanf("%d%d%d%d", &s, &l, &r, &y); scanf("%*c");
            if (T == 1) y ^= A;
            l = findPlayer(s, l);
            r = findPlayer(s, r);
            split(l, r);
            pushdownMul(r, y);
        } else {
            scanf("%d%d%d", &s, &l, &r); scanf("%*c");
            l = findPlayer(s, l); r = findPlayer(s, r);
            split(l, r); A = sum[r]; printf("%d\n", A);
        }
    }
    return 0;
}

Leetcode

Question Table Leetcode

序号题目状态备注
1Two Sum完成[题目链接](#Question 1: Two Sum),暴力破解, 哈希表
2Add Two Numbers完成[题目链接](#Question 2: addTwoNumbers),链表, 处理细节
3Length Of Longest Substring完成[题目链接](#Question 3: lengthOfLongestSubstring),滑动窗口,哈希表
4Median of Two Sorted Arrays完成[题目链接](#Question 4: medianOfTwoSortedArrays),二分搜索,双指针
5Longest palindromic Substring完成[题目链接](#Question 5: longestPalindrome),動態規劃、中心擴散、馬拉度
6Zig Zag Conversion完成[题目链接](#Question 6: ZigZagConversion)
7Reverse Integer完成[题目链接](#Question 7: Reverse Integer),模拟
8String to Integer(atoi)完成[题目链接](#Question 8: String to Integer (atoi)),自动机,模拟

Question 1: Two Sum

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

参考题解

Optional C++

C++ Main 的代码仓库

Optional Rust

Rust Main的代码仓库

Question 2: addTwoNumbers

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

参考代码

Optional C++
struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
    struct Simulation {};
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        return addTwoNumberImpl(Simulation(), l1, l2);
    }

    ListNode* addTwoNumberImpl(Simulation, ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;
        int carry = 0;
        while (l1 || l2) {
            int n1 = l1 ? l1->val : 0;
            int n2 = l2 ? l2->val : 0;
            int sum = n1 + n2 + carry;
            if (!head) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) l1 = l1->next;
            if (l2) l2 = l2->next;
        }
        if (carry > 0) tail->next = new ListNode(carry);
        return head;
    }
};
Optional Rust
// You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
//
// You may assume the two numbers do not contain any leading zero, except the number 0 itself.
// Example 1
//     Input: l1 = [2,4,3], l2 = [5,6,4]
//     Output: [7,0,8]
//     Explanation: 342 + 465 = 807.
// 
// Example 2:
//     Input: l1 = [0], l2 = [0]
//     Output: [0]
//     Example 3:
// 
// Example 3:
//     Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
//     Output: [8,9,9,9,0,0,0,1]
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
  pub val: i32,
  pub next: Option<Box<ListNode>>
}

impl ListNode {
  #[inline]
  fn new(val: i32) -> Self {
    ListNode {
      next: None,
      val
    }
  }
  #[inline]
  fn _new(val: i32, next: Option<Box<ListNode>>) -> Self {
    ListNode {
      next,
      val
    }
  }
}
trait SolutionMethod {
    fn add_two_numbers_impl(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>>;
}

struct Simulation {}

impl SolutionMethod for Simulation {
    fn add_two_numbers_impl(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let mut _l1 = l1;
        let mut _l2 = l2;
        let mut _head = Some(Box::new(ListNode::new(0)));
        let mut _tail = &mut _head;
        let mut _carry = 0;

        while _l1.is_some() || _l2.is_some() {
            match _tail {
                Some(_list_node) => {
                    let mut _1 = _l1.take().unwrap_or(Box::new(ListNode::new(0)));
                    let mut _2 = _l2.take().unwrap_or(Box::new(ListNode::new(0)));
                    let mut sum = _1.val + _2.val + _carry;
                    _carry = sum / 10; sum  = sum % 10;
                    _list_node.next.get_or_insert(Box::new(ListNode::new(sum)));
                    _tail = &mut _list_node.next;
                    // if _l1.is_some() { _l1 = _1.next; }
                    // if _l2.is_some() { _l2 = _2.next; }
                    _l1 = _1.next; _l2 = _2.next;
                },
                None => break,
            }
        }

        if _carry == 1 {
            if let Some(_carry_node) = _tail {
                _carry_node.next.get_or_insert(Box::new(ListNode::new(1)));
            }
        }
        _head.unwrap().next
    }
}

pub struct Solution {}

impl Solution {
    pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        <Simulation as SolutionMethod>::add_two_numbers_impl(l1, l2)
    }
}


#[cfg(test)]
mod question_2_leetcode_test {
    use super::*;
    #[test]
    fn test_question() {
        let mut _header1: Option<Box<ListNode>> = None;
        let mut _header2: Option<Box<ListNode>> = None;
        let mut _header3: Option<Box<ListNode>> = None;
        let mut _item1 = &mut _header1;
        let mut _item2 = &mut _header2;
        let mut _item3 = &mut _header3;
        // [2 4 3] [5 6 4]
        _item1.insert(Box::new(ListNode::new(2)));
        _item1.as_mut().unwrap().next.get_or_insert(Box::new(ListNode::new(4)));
        _item1.as_mut().unwrap().next.as_mut().unwrap().next.get_or_insert(Box::new(ListNode::new(3)));

        _item2.insert(Box::new(ListNode::new(5)));
        _item2.as_mut().unwrap().next.get_or_insert(Box::new(ListNode::new(6)));
        _item2.as_mut().unwrap().next.as_mut().unwrap().next.get_or_insert(Box::new(ListNode::new(4)));


        _item3.insert(Box::new(ListNode::new(7)));
        _item3.as_mut().unwrap().next.get_or_insert(Box::new(ListNode::new(0)));
        _item3.as_mut().unwrap().next.as_mut().unwrap().next.get_or_insert(Box::new(ListNode::new(8)));
        println!("List: 1       {:?}", _header1);
        println!("List: 2       {:?}", _header2);
        let l1 =  _header1; let l2 =  _header2;

        let ans = Solution::add_two_numbers(l1, l2);

        println!("List: expect  {:?}", _header3);
        println!("List: ans     {:?}", ans);
        assert_eq!(_header3, ans);
    }
}


Question 3: lengthOfLongestSubstring

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

参考代码

Optional C++
#include <vector>
#include <unordered_map>

class Solution {
    struct WindowWithHashTable {};
    struct WindowWithArray {};
public:
    int lengthOfLongestSubstring(std::string s) {
        return lengthOfLongestSubstringImpl(WindowWithArray(), s);
    }
    int lengthOfLongestSubstringImpl(WindowWithHashTable, std::string &s) {
        int start(0), end(0), length(0), result(0);
        int s_size = s.size();
        std::unordered_map<char, int> hashTable;
        while (end < s_size) {
            char tmp_char = s[end];
            if (hashTable.find(tmp_char) != hashTable.end() && hashTable[tmp_char] >= start) {
                start = hashTable[tmp_char] + 1;
                length = end - start;
            }
            hashTable[tmp_char] = end;
            end++;length++;
            result = std::max(result, length);
        }
        return result;

    }
    int lengthOfLongestSubstringImpl(WindowWithArray, std::string &s) {
        int start(0), end(0), length(0), result(0);
        int s_size = s.size();
        std::vector<int> vec(128, -1);
        // FIXME: There is wrong in code [" ", 1, 0] in std::array
        // std::array<int, 128> arr = {0};
        while (end < s_size) {
            char tmp_char = s[end];
            if (! (vec[tmp_char] < start)) {
                start =  vec[tmp_char] + 1;
                length = end - start;
            }
            vec[tmp_char] = end;
            end++; length++;
            result = std::max(result, length);
        }
        return result;
    }
};

Optional Rust
// Given a string s, find the length of the longest substring without repeating characters.
// 
// Example 1:
// 
//     Input: s = "abcabcbb"
//     Output: 3
//     Explanation: The answer is "abc", with the length of 3.
// Example 2:
// 
//     Input: s = "bbbbb"
//     Output: 1
//     Explanation: The answer is "b", with the length of 1.
// Example 3:
// 
//     Input: s = "pwwkew"
//     Output: 3
//     Explanation: The answer is "wke", with the length of 3.
// Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.

use std::collections::HashMap;

trait SolutionMethod {
    fn length_of_longest_substring_impl(s: String) -> i32;
}

struct WindowWithHashTable {}

impl SolutionMethod for WindowWithHashTable {
    fn length_of_longest_substring_impl(s: String) -> i32 {
        let mut _window = HashMap::new();
        let (mut start, mut res) = (0, 0);
        for (end, ch) in s.chars().enumerate() {
            if let Some(pos) = _window.get(&ch) {
                start = start.max(*pos);
            }
            res = res.max(end + 1 - start);
            _window.insert(ch, end+1);
        }
        res as i32
    }
}

struct WindowWithVec {}

impl SolutionMethod for WindowWithVec {
    fn length_of_longest_substring_impl(s: String) -> i32 {
        let (mut ret, mut l, mut cache) = (0, 0, vec![0; 128]); // There is a problem with cache.len()
        s.chars().enumerate().for_each(|(i, ch)| {
            l = l.max(cache[ch as usize]);
            ret = ret.max(i as i32 - l + 1);
            cache[ch as usize] = i as i32 + 1;
        });
        ret
    }
}


struct Solution {}

impl Solution {
    pub fn length_of_longest_substring(s: String) -> i32 {
        <WindowWithHashTable as SolutionMethod>::length_of_longest_substring_impl(s)
    }
}

#[cfg(test)]
mod question_3_leetcode_test {
    use super::*;

    #[test]
    fn test_question() {
        assert_eq!(3i32, Solution::length_of_longest_substring("abcabcbb".into()));
        assert_eq!(1i32, Solution::length_of_longest_substring("bbbbb".into()));
        assert_eq!(3i32, Solution::length_of_longest_substring("pwwkew".into()));
    }

}

Question 4: medianOfTwoSortedArrays

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

参考代码

Optional C++
class Solution {
    struct BinarySearch {};
    struct DoublePointer {};
    static int get_k_th_element(const std::vector<int>& nums1, const std::vector<int>& nums2, int k) {
        /* 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
         * 这里的 "/" 表示整除
         * nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
         * nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
         * 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
         * 这样 pivot 本身最大也只能是第 k-1 小的元素
         * 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
         * 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
         * 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
         */

        int m = nums1.size();
        int n = nums2.size();
        int index1 = 0, index2 = 0;

        while (true) {
            // 边界情况
            if (index1 == m) {
                return nums2[index2 + k - 1];
            }
            if (index2 == n) {
                return nums1[index1 + k - 1];
            }
            if (k == 1) {
                return std::min(nums1[index1], nums2[index2]);
            }

            // 正常情况
            int newIndex1 = std::min(index1 + k / 2 - 1, m - 1);
            int newIndex2 = std::min(index2 + k / 2 - 1, n - 1);
            int pivot1 = nums1[newIndex1];
            int pivot2 = nums2[newIndex2];
            if (pivot1 <= pivot2) {
                k -= newIndex1 - index1 + 1;
                index1 = newIndex1 + 1;
            }
            else {
                k -= newIndex2 - index2 + 1;
                index2 = newIndex2 + 1;
            }
        }
    }
public:
    double findMedianSortedArrays(std::vector<int>& nums1, std::vector<int>& nums2) {
        return findMedianSortedArraysImpl(BinarySearch(), nums1, nums2);
    }
    double findMedianSortedArraysImpl(BinarySearch, std::vector<int>& nums1, std::vector<int>& nums2) {
                int totalLength = nums1.size() + nums2.size();
        if (totalLength % 2 == 1) {
            return get_k_th_element(nums1, nums2, (totalLength + 1) / 2);
        }
        else {
            return (get_k_th_element(nums1, nums2, totalLength / 2) + get_k_th_element(nums1, nums2, totalLength / 2 + 1)) / 2.0;
        }
    }
    double findMedianSortedArraysImpl(DoublePointer, std::vector<int>& nums1, std::vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size(), i = 0, j = 0, p = 0, q = 0, _ = 0;
        int len = n + m;
    Loop:
        if (! (((_) << 1) < len + 1) ) goto End; p = q;
        if (i < m && (j >= n || nums1[i] < nums2[j])) {
            q = nums1[i]; ++i;
        } else {
            q = nums2[j]; ++j;
        }
        ++_; goto Loop;
    End:
        return(len & 1) ? q : (p + q) / 2.0;
    }
};

Optional Rust
// Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
// 
// The overall run time complexity should be O(log (m+n)).
// 
// Example 1:
// 
//     Input: nums1 = [1,3], nums2 = [2]
//     Output: 2.00000
//     Explanation: merged array = [1,2,3] and median is 2.
// Example 2:
// 
//     Input: nums1 = [1,2], nums2 = [3,4]
//     Output: 2.50000
//     Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.
use std::cmp::min;

trait SolutionMethod {
    fn find_median_sorted_arrays_impl(nums1: Vec<i32>, nums2: Vec<i32>) -> f64;
}

struct Abandon {}

impl SolutionMethod for Abandon {
    fn find_median_sorted_arrays_impl(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
        let mut nums1 = nums1;
        let mut nums2 = nums2;
        nums1.append(&mut nums2);
        nums1.sort();
        let len = nums1.len();
        if len <= 1 {
            return nums1[0] as f64 ;
        }
        match len % 2 {
            1 => nums1[len/2] as f64,
            0 => (nums1[len/2]+nums1[len/2-1]) as f64/2.0,
            _ => 0.0f64,
        }
    }
}


struct BinarySearch {}

impl BinarySearch {
    fn find_k(v1: &Vec<i32>, i: usize, v2: &Vec<i32>, j: usize, k: usize) -> i32 {
    // 当nums1 删除完,则直接返回j+k-1位置的数字,nums2删完同理
        if i >= v1.len() {
            return v2[j + k - 1]
        }
        if j >= v2.len() {
            return v1[i + k - 1]
        }
        // k==1时表示找最小的数字
        if k == 1 {
            return min(v1[i], v2[j]);
        }
        let max1 = if (i + k/2 - 1) < v1.len() { v1[i + k/2 - 1] } else { i32::MAX };
        let max2 = if (j + k/2 - 1) < v2.len() { v2[j + k/2 - 1] } else { i32::MAX };
        if max1 > max2 {
            Self::find_k(v1, i, v2, j + k / 2, k - k / 2)
        } else {
            Self::find_k(v1, i + k / 2, v2, j, k - k / 2)
        }
    }
}

impl SolutionMethod for BinarySearch {
    fn find_median_sorted_arrays_impl(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
        let min_left = (nums1.len() + nums2.len() + 1) / 2;
        let min_right = (nums1.len() + nums2.len() + 2) / 2;
        (Self::find_k(&nums1, 0, &nums2, 0, min_left) + Self::find_k(&nums1, 0, &nums2, 0, min_right)) as f64 / 2.0
    }
}

struct DoublePointer {}

impl SolutionMethod for DoublePointer {
    fn find_median_sorted_arrays_impl(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
        let m = nums1.len();
        let n = nums2.len();
        let len = m + n;

        let mut i: usize = 0; let mut j: usize = 0;
        let mut p = 0i32; let mut q = 0i32;

        for _ in 0..len / 2 + 1 {
            p = q;
            if i < m && (j >= n || nums1[i] < nums2[j]) {
                q = nums1[i]; i += 1;
            } else {
                q = nums2[j]; j += 1;
            }
        }

        if len & 1 == 0 { (p + q) as f64 / 2.0 } else { q as f64 }
    }
}

pub struct Solution {}

impl Solution {
    pub fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
        <DoublePointer as SolutionMethod>::find_median_sorted_arrays_impl(nums1, nums2)
    }
}

#[cfg(test)]
mod question_4_leetcode_test {
    use super::*;
    #[test]
    fn test_question() {
        let ans = Solution::find_median_sorted_arrays(vec![1, 2], vec![3, 4]);
        assert_eq!(ans, 2.50000);
    }
}

Question 5: longestPalindrome

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

參考代碼

Optional C++
class Solution {
    struct DynamicProgramming {};
    struct CenterDiffusion {};
    std::pair<int, int> expandAroundCenter(const std::string& s, int left, int right) {
            while (left >= 0 && right < s.size() && s[left] == s[right]) {
                --left;
                ++right;
            }
            return {left + 1, right - 1};
        }
    struct Manacher {};
    int expand(const std::string& s, int left, int right) {
        while (left >= 0 && right < s.size() && s[left] == s[right]) {
            --left;
            ++right;
        }
        return (right - left - 2) / 2;
    }
public:
    std::string longestPalindromeImpl(DynamicProgramming, std::string s) {
        int n = s.size();
        if (n < 2) {
            return s;
        }

        int maxLen = 1;
        int begin = 0;
        // dp[i][j] 表示 s[i..j] 是否是回文串
        std::vector<std::vector<int>> dp(n, std::vector<int>(n));
        // 初始化:所有长度为 1 的子串都是回文串
        for (int i = 0; i < n; i++) {
            dp[i][i] = true;
        }
        // 递推开始
        // 先枚举子串长度
        for (int L = 2; L <= n; L++) {
            // 枚举左边界,左边界的上限设置可以宽松一些
            for (int i = 0; i < n; i++) {
                // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
                int j = L + i - 1;
                // 如果右边界越界,就可以退出当前循环
                if (j >= n) {
                    break;
                }

                if (s[i] != s[j]) {
                    dp[i][j] = false;
                } else {
                    if (j - i < 3) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substr(begin, maxLen);
    }
    std::string longestPalindromeImpl(CenterDiffusion, std::string s) {
        int start = 0, end = 0;
        for (int i = 0; i < s.size(); ++i) {
            auto [left1, right1] = expandAroundCenter(s, i, i);
            auto [left2, right2] = expandAroundCenter(s, i, i + 1);
            if (right1 - left1 > end - start) {
                start = left1;
                end = right1;
            }
            if (right2 - left2 > end - start) {
                start = left2;
                end = right2;
            }
        }
        return s.substr(start, end - start + 1);
    }
    std::string longestPalindromeImpl(Manacher, std::string s) {
        int start = 0, end = -1;
        std::string t = "#";
        for (char c: s) {
            t += c;
            t += '#';
        }
        t += '#';
        s = t;

        std::vector<int> arm_len;
        int right = -1, j = -1;
        for (int i = 0; i < s.size(); ++i) {
            int cur_arm_len;
            if (right >= i) {
                int i_sym = j * 2 - i;
                int min_arm_len = std::min(arm_len[i_sym], right - i);
                cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
            } else {
                cur_arm_len = expand(s, i, i);
            }
            arm_len.push_back(cur_arm_len);
            if (i + cur_arm_len > right) {
                j = i;
                right = i + cur_arm_len;
            }
            if (cur_arm_len * 2 + 1 > end - start) {
                start = i - cur_arm_len;
                end = i + cur_arm_len;
            }
        }

        std::string ans;
        for (int i = start; i <= end; ++i) {
            if (s[i] != '#') {
                ans += s[i];
            }
        }
        return ans;
    }
    std::string longestPalindrome(std::string s) {
        return longestPalindromeImpl(DynamicProgramming(), s);
    }
};

Optional Rust
// Given a string s, return the longest palindromic substring in s.
// 
// Example 1:
// 
//     Input: s = "babad"
//     Output: "bab"
//     Explanation: "aba" is also a valid answer.
// Example 2:
// 
//     Input: s = "cbbd"
//     Output: "bb"
trait SolutionMethod {
    fn longest_palindrome_impl(s: String) -> String;
}

struct DynamicProgramming {}

impl SolutionMethod for DynamicProgramming {
    fn longest_palindrome_impl(s: String) -> String {
        let arr: Vec<char> = s.chars().collect();
        let mut start_idx = 0usize;
        let mut max = 1usize;
        let count = s.chars().count();
        // 初始化dp的是时候,就插入表示 每个位置的单个字符就是回文
        let mut dp: Vec<Vec<bool>> = (0..count).map(|_| { vec![false; count] }).collect();
        for size in 2..=count {
            for i in 0..count {
                let j = size + i - 1;
                if j >= count {
                    break;
                }
                if arr[i] == arr[j] {
                    if size >= 4 {
                        dp[i][j] = dp[i + 1][j - 1];
                    } else {
                        dp[i][j] = true;
                    }
                } else {
                    dp[i][j] = false;
                }
                if dp[i][j] && size > max {
                    max = size;
                    start_idx = i;
                }
            }
        }
        arr.iter().enumerate()
            .filter(|&(i, _)| i >= start_idx && i < start_idx + max)
            .map(|(_, v)| v)
            .collect()
    }
}


struct Manacher {}

impl Manacher {
    fn check(s: &Vec<char>, mut lt: usize, mut rt: usize) -> usize {
        while rt < s.len() && s[lt] == s[rt] {
            if lt == 0 {
                return rt - lt + 1;
            }
            lt -= 1;
            rt += 1;
        }
        rt - lt - 1 // (rt - 1) - (lt + 1) + 1 = rt - lt - 1
    }
}

impl SolutionMethod for Manacher {
    fn longest_palindrome_impl(s: String) -> String {
        let mut start_idx = 0;
        let mut max_len = 1;
        let mut arr_chars = vec!['#'];
        for c in s.chars() {
            arr_chars.push(c);
            arr_chars.push('#');
        }
        let len =  arr_chars.len();
        let mut center = 0;
        let mut r = 0;
        let mut r_arr = vec![0; len];
        for i in 0..len {
            let tmp_len = if i < center + r {
                let tmp_dis = (center + r - i).min(r_arr[2 * center - i]);
                Self::check(&arr_chars, i - tmp_dis - 1, i + tmp_dis + 1)
            } else {
                Self::check(&arr_chars, i, i)
            };
            let tmp_r = (tmp_len - 1) / 2; // get radis
            r_arr[i] = tmp_r;

            if tmp_len > max_len {
                max_len = tmp_len;
                start_idx = i - (tmp_len - 1) / 2;
            }
            // set center and r 
            if i + tmp_r + 1 > center + r {
                center = i;
                r = tmp_r;
            }
        }
        arr_chars.iter().enumerate()
            .filter(|&(i, _)| i >= start_idx && i < start_idx + max_len && i & 1 != 0)
            .map(|(_, v)| v)
            .collect()
    }
}

struct CenterDiffusion {}

impl CenterDiffusion {}

impl CenterDiffusion {
    fn check(s: &Vec<char>, mut lt: usize, mut rt: usize) -> (usize, usize) {
        while rt < s.len() && s[lt] == s[rt] {
            if lt == 0 {
                return (0, rt + 1)
            }
            lt -= 1;
            rt += 1;
        }
        (lt + 1, rt - lt - 1)
    }
}

impl SolutionMethod for CenterDiffusion {
    fn longest_palindrome_impl(s: String) -> String {
        let arr: Vec<char> = s.chars().collect();
    let (mut start_idx, mut max) = (0, 1);
    for i in 0..arr.len() {
        let (start1, len1) = Self::check(&arr, i, i);
        let (start2, len2) = Self::check(&arr, i, i + 1);
        if len2 > len1 {
            if len2 > max {
                start_idx = start2;
                max = len2;
            } 
        } else {
            if len1 > max {
                start_idx = start1;
                max = len1;
            }
        }
    }
    arr.iter().enumerate()
        .filter(|&(i, _)| i >= start_idx && i < start_idx + max)
        .map(|(_, v)| v)
        .collect()
    }
}

pub struct Solution {}

impl Solution {
    pub fn longest_palindrome(s: String) -> String {
        <CenterDiffusion as SolutionMethod>::longest_palindrome_impl(s)
    }
}

#[cfg(test)]
mod question_5_leetcode_test {
    use super::*;
    #[test]
    fn test_question() {
        assert_eq!("bab".to_string(), Solution::longest_palindrome("babad".to_string()));
        assert_eq!("bb".to_string(), Solution::longest_palindrome("cbbd".to_string()));
    }
}

Question 6: ZigZagConversion

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

參考代碼

Optional C++
class Solution {
    struct MatrixSimulation {};
    struct MatrixCompression {};
    struct Construction {};
public:
    std::string convertImpl(MatrixSimulation, std::string s, int numRows) {
        int n = s.length(), r = numRows;
        if (r == 1 || r >= n) {
            return s;
        }
        int t = r * 2 - 2;
        int c = (n + t - 1) / t * (r - 1);
        std::vector<std::string> mat(r, std::string(c, 0));
        for (int i = 0, x = 0, y = 0; i < n; ++i) {
            mat[x][y] = s[i];
            if (i % t < r - 1) {
                ++x; // 向下移动
            } else {
                --x;
                ++y; // 向右上移动
            }
        }
        std::string ans;
        for (auto &row : mat) {
            for (char ch : row) {
                if (ch) {
                    ans += ch;
                }
            }
        }
        return ans;
    }
    std::string convertImpl(MatrixCompression, std::string s, int numRows) {
        int n = s.length(), r = numRows;
        if (r == 1 || r >= n) {
            return s;
        }
        std::vector<std::string> mat(r);
        for (int i = 0, x = 0, t = r * 2 - 2; i < n; ++i) {
            mat[x] += s[i];
            i % t < r - 1 ? ++x : --x;
        }
        std::string ans;
        for (auto &row : mat) {
            ans += row;
        }
        return ans;
    }
    std::string convertImpl(Construction, std::string s, int numRows) {
        int n = s.length(), r = numRows;
        if (r == 1 || r >= n) {
            return s;
        }
        std::string ans;
        int t = r * 2 - 2;
        for (int i = 0; i < r; ++i) { // 枚举矩阵的行
            for (int j = 0; j + i < n; j += t) { // 枚举每个周期的起始下标
                ans += s[j + i]; // 当前周期的第一个字符
                if (0 < i && i < r - 1 && j + t - i < n) {
                    ans += s[j + t - i]; // 当前周期的第二个字符
                }
            }
        }
        return ans;
    }
    std::string convert(std::string s, int numRows) {
        return convertImpl(MatrixSimulation(), s, numRows);
    }
};
Optional Rust
// The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
// 
// P   A   H   N
// A P L S I I G
// Y   I   R
// And then read line by line: "PAHNAPLSIIGYIR"
// 
// Write the code that will take a string and make this conversion given a number of rows:
// 
// string convert(string s, int numRows);
//  
// 
// Example 1:
// 
//     Input: s = "PAYPALISHIRING", numRows = 3
//     Output: "PAHNAPLSIIGYIR"
// Example 2:
// 
//     Input: s = "PAYPALISHIRING", numRows = 4
//     Output: "PINALSIGYAHRPI"
//     Explanation:
//     P     I    N
//     A   L S  I G
//     Y A   H R
//     P     I
// Example 3:
// 
//     Input: s = "A", numRows = 1
//     Output: "A"
trait SolutionMethod {
    fn convert_impl(s: String, num_rows: i32) -> String;
}

struct MatrixSimulation {}

impl SolutionMethod for MatrixSimulation {
    fn convert_impl(s: String, num_rows: i32) -> String {
        // 为什么输入类型总是i32
        let num_rows = num_rows as usize;
        // 每行一个String
        let mut rows = vec![String::new(); num_rows];
        // z字形往复的迭代器,01232101232......
        let iter = (0..num_rows).chain((1..num_rows-1).rev()).cycle();
        // 按迭代器给出的下标访问对应行,推入字符
        iter.zip(s.chars()).for_each(|(i, c)| rows[i].push(c));
        // collect连接每行
        rows.into_iter().collect()
    }
}
struct MatrixCompression {}

impl SolutionMethod for MatrixCompression {
    fn convert_impl(s: String, num_rows: i32) -> String {
        let (n, r) = (s.len(), num_rows as usize);
        if r == 1 || r >= n {
            return s;
        }

        s.chars()
            .collect::<Vec<char>>()
            .iter()
            .enumerate()
            .fold((vec![String::new(); r], 0), |(mut mat, mut x), (i, ch)| {
                mat.get_mut(x).unwrap_or(&mut String::new()).push(*ch);
                if i % (r * 2 - 2) < r - 1 {
                    x += 1;
                } else {
                    x -= 1;
                }
                (mat, x)
            })
            .0
            .join("")
    }
}

struct Construction {}

impl SolutionMethod for Construction {
    fn convert_impl(s: String, num_rows: i32) -> String {
        let (n, r) = (s.len(), num_rows as usize);
        if r == 1 || r >= n {
            return s;
        }

        let s = s.chars().collect::<Vec<char>>();
        let mut ans = String::new();
        for i in 0..r {
            for j in (0..n - i).step_by(r * 2 - 2) {
                ans.push(s[j + i]);
                if 0 < i && i < r - 1 && j + (r * 2 - 2) - i < n {
                    ans.push(s[j + (r * 2 - 2) - i]);
                }
            }
        }
        ans
    }
}


struct Solution {}


impl Solution {
    pub fn convert(s: String, num_rows: i32) -> String {
        <MatrixSimulation as SolutionMethod>::convert_impl(s, num_rows)
    }
}

Question 7: Reverse Integer

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

參考代碼

Optional C++
class Solution  {
    public:
    int reverse(int x) {
        int rev = 0;
        while (0 != x) {
            if (rev < std::numeric_limits<int>::min() / 10 || rev > std::numeric_limits<int>::max() / 10) {
                return 0;
            }
            int digit = x % 10;
            x /= 10;
            rev = 10 * rev + digit;
        }
        return rev;
    }
};
Optional Rust
struct SolutionMethod {
    fn reverse(x: i32) -> i32;
}

struct Abandon {}

impl SolutionMethod for Abandon {
     fn reverse(x: i32) -> i32 {
       x.abs()
        .to_string()
        .chars().rev()
        .collect::<String>()
        .parse::<i32>()
        .unwrap_or(0) * x.signum()
    }
}


impl Solution {
    pub fn reverse(x: i32) -> i32 {
		<Abandon as SolutionMethod>::reverse(x)
    }
}

Question 8: String to Integer (atoi)

[ 🏚 Question Table Leetcode ](#Question Table Leetcode)

參考代碼

Optional C++
class Automaton {
    friend class Solution;
    std::string state = "start";
    std::unordered_map<std::string, std::vector<std::string>> table = {
        {"start", {"start", "signed", "in_number", "end"}},
        {"signed", {"end", "end", "in_number", "end"}},
        {"in_number", {"end", "end", "in_number", "end"}},
        {"end", {"end", "end", "end", "end"}}
    };

    int get_col(char c) {
        if (isspace(c)) return 0;
        if (c == '+' or c == '-') return 1;
        if (isdigit(c)) return 2;
        return 3;
    }
    public:
    int sign = 1;
    long ans = 0;

    void get(char c) {
        state = table[state][get_col(c)];
        if (state == "in_number") {
            ans = ans * 10 + c - '0';
            ans = sign == 1 ? std::min(ans, static_cast<long>(std::numeric_limits<int>::max())) : std::min(ans, -1 * static_cast<long>(std::numeric_limits<int>::min()));
        }
        else if (state == "signed")
            sign = c == '+' ? 1 : -1;
    }
};

class Solution {
    struct AutomatonMethod {};
    struct NormalMethod {};
    public:
    int myAtoiImpl(NormalMethod, std::string str) {
        int i = 0; bool isNegative = false; long ans = 0;
        const unsigned int UNSIGNED_INT_MAX = static_cast<unsigned int>(std::numeric_limits<int>::max());
        while (' ' == str[i]) ++i;
        if ('-' == str[i]) {
            isNegative = true; ++i;
        } else if ('+' == str[i]) {
            ++i;
        }
        while ('0' <= str[i] && '9' >= str[i] && UNSIGNED_INT_MAX >= ans) {
            ans = ans * 10 + str[i] - '0';
            ++i;
        }
        return !isNegative ?
            (UNSIGNED_INT_MAX < ans ? UNSIGNED_INT_MAX : ans) :
        -1 * (UNSIGNED_INT_MAX < ans ? UNSIGNED_INT_MAX + 1 : ans);
    }
    int myAtoiImpl(AutomatonMethod, std::string str) {
        Automaton automaton;
        for (char c : str) automaton.get(c);
        return automaton.sign * automaton.ans;
    }
    int myAtoi(std::string str) {
        return myAtoiImpl(NormalMethod(), str);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值