L58.【LeetCode題解】模擬算法習題集1(Z 字形變換、外觀數列)

目錄

1.Z 字形變換

方法1: 模擬

代碼

提交結果

方法2:優化后的模擬

代碼

提交結果

2.外觀數列

方法1:模擬

代碼

提交結果

方法2:打表

知識回顧

代碼


1.Z 字形變換

https://leetcode.cn/problems/zigzag-conversion/

將一個給定字符串 s 根據給定的行數 numRows ,以從上往下、從左到右進行?Z 字形排列。

比如輸入字符串為 "PAYPALISHIRING"?行數為 3 時,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的輸出需要從左往右逐行讀取,產生出一個新的字符串,比如:"PAHNAPLSIIGYIR"

請你實現這個將字符串進行指定行數變換的函數:

string convert(string s, int numRows);

示例 1:

輸入:s = "PAYPALISHIRING", numRows = 3
輸出:"PAHNAPLSIIGYIR"

示例 2:

輸入:s = "PAYPALISHIRING", numRows = 4
輸出:"PINALSIGYAHRPI"
解釋:
P     I    N
A   L S  I G
Y A   H R
P     I

示例 3:

輸入:s = "A", numRows = 1
輸出:"A"

提示:

  • 1 <= s.length <= 1000
  • s 由英文字母(小寫和大寫)、',''.' 組成
  • 1 <= numRows <= 1000

方法1: 模擬

Z 字形圖示(其實看起來是N字形)

由于s.length和numRows的取值范圍比較窄,因此可以創建一個1000*1000的char數組(不放心可以設大一些)

將連在一起的Z字形拆分成形狀相同的部分

可以算出每一部分列數part_size_col為part_size-numRows+1,行數為numRows

可以算出每一部分字符的個數都是2 * numRows - 2個?

對于每一個部分,填字符分兩步:1.豎著填 2.斜著填

最后打印vector<string>時要算清右多少行

先算算有多少個完整的部分:s.size()/part_size,它們一共占(s.size()/part_size)*part_size_col行,剩下來殘缺的部分不超過part_size_col行,因此可以按(s.size()/part_size)*part_size_col+part_size_col來控制行所以

代碼

注:numRows == 1要特殊處理

class Solution {
public:string convert(string s, int numRows){if (numRows==1){return s;}char arr[1010][1010];string ret;memset(arr, '\0', sizeof(arr));int row = 0;int col = 0;int part_size = 2 * numRows - 2;int part_size_col=part_size-numRows+1;int total_col=(s.size()/part_size)*part_size_col+part_size_col;for (int i = 0; i < s.size(); i++){if (i % part_size >= 0 && i % part_size <= numRows - 1){//豎著填arr[row][col] = s[i];row++;}else{//斜著填arr[row][col] = s[i];row--;col++;}if (i % part_size == numRows - 1){col++;row = numRows - 2;}}for (int i = 0; i < numRows; i++){for (int j = 0; j <total_col; j++){if (arr[i][j] != '\0')ret.push_back(arr[i][j]);}}return ret;}
};

提交結果

方法2:優化后的模擬

可使用模擬算法解的絕大部分題的優化方法是找規律

由特殊到一般,以s = "PAYPALISHIRING", numRows = 4為例,將字符在字符串中對應的下標填寫到二維數組中

0  6  12  
1 57 1113  
24 810    
3  9     

分行看規律:

第0行:0,6,12

第n-1行:3,9

會發現第0行和第n-1行的相鄰元素都差6,而6是2 * numRows - 2的值(可自行多找一個樣例驗證)

第1行~第n-2行:

兩兩一組看:

第1行: 1,5,? ? 7,11,? ? 13

第2行:2,4,? ? 8,10

可得出如下規律:第k行: k,d-k,? ? k+d,2d-k,? ? k+2d,3d-k,......,k+nd,(n+1)d-k,其中(n+1)d-k<s.size()

代碼

注:numRows == 1要特殊處理

class Solution {
public:string convert(string s, int numRows){if (numRows == 1)return s;string ret;int d = 2 * numRows - 2;//第0行int firstrow_i = 0;while (firstrow_i < s.size()){ret.push_back(s[firstrow_i]);firstrow_i += d;}//第1~(numRows-2)行for (int row = 1; row < numRows-1; row++){int i = row;while (i < s.size()){ret.push_back(s[i]);if (i + d - 2 * row < s.size())ret.push_back(s[i + d - 2 * row]);i += d;}}//第numRows-1行int lastrow_i = numRows - 1;while (lastrow_i < s.size()){ret.push_back(s[lastrow_i]);lastrow_i += d;}return ret;}
};

提交結果

2.外觀數列

https://leetcode.cn/problems/count-and-say/

「外觀數列」是一個數位字符串序列,由遞歸公式定義:

  • countAndSay(1) = "1"
  • countAndSay(n) 是?countAndSay(n-1) 的行程長度編碼。

    行程長度編碼(RLE)是一種字符串壓縮方法,其工作原理是通過將連續相同字符(重復兩次或更多次)替換為字符重復次數(運行長度)和字符的串聯。例如,要壓縮字符串?"3322251"?,我們將?"33"?用?"23"?替換,將?"222"?用?"32"?替換,將?"5"?用?"15"?替換并將?"1"?用?"11"?替換。因此壓縮后字符串變為 "23321511"

    給定一個整數?n?,返回?外觀數列?的第?n?個元素。

    示例 1:

    輸入:n = 4

    輸出:"1211"

    解釋:

    countAndSay(1) = "1"

    countAndSay(2) = "1" 的行程長度編碼 = "11"

    countAndSay(3) = "11" 的行程長度編碼 = "21"

    countAndSay(4) = "21" 的行程長度編碼 = "1211"

    示例 2:

    輸入:n = 1

    輸出:"1"

    解釋:

    這是基本情況。

    提示:

    • 1 <= n <= 30

    進階:你能迭代解決該問題嗎?

    方法1:模擬

    countAndSay(1) = "1",countAndSay(2)應該表示"1",即1個1,所以countAndSay(2)="11"

    countAndSay(3)應該表示"11",即2個1,所以countAndSay(3)="21"

    countAndSay(4)應該表示"21",即1個2,1個1,所以countAndSay(4)="1211"

    countAndSay(5)應該表示"1211",即1個1,1個2,2個1,所以countAndSay(4)="111221"

    循環即可,

    代碼

    class Solution {
    public:string countAndSay(int n)//非遞歸,使用vector<string>存儲從1~n的外觀數列{vector<string> arr;arr.push_back("");arr.push_back("1");for (int i = 2; i <= n; i++){string tmp;int num = 0;char ch = arr[i - 1][0];for (int j = 0; j < arr[i - 1].size(); j++){if (arr[i - 1][j] == ch)num++;else{tmp = tmp + to_string(num);tmp.push_back(ch);ch = arr[i - 1][j];num = 1;}}if (num){tmp = tmp + to_string(num);tmp.push_back(ch);}arr.push_back(tmp);}return arr[n];}
    };

    提交結果

    或者不使用vector<string>,只保留第n個外觀數列

    class Solution {
    public:string countAndSay(int n)//非遞歸,只保留第n個外觀數列{string s="1";for (int i = 2; i <= n; i++){string tmp;int num = 0;char ch = s[0];for (int j = 0; j < s.size(); j++){if (s[j] == ch)num++;else{tmp = tmp + to_string(num);tmp.push_back(ch);ch = s[j];num = 1;}}if (num){tmp = tmp + to_string(num);tmp.push_back(ch);}s=tmp;}return s;}
    };
    

    提交結果:

    ?

    或者使用雙指針:

    以"111221"為例:

    left和right之間1的個數為right-left

    class Solution {
    public:string countAndSay(int n)//雙指針{string s = "1";for (int i = 2; i <= n; i++){string tmp;int left = 0;int right = 0;while (1){if (s[left] == s[right]){right++;if (right == s.size()){tmp = tmp + to_string(right - left);tmp.push_back(s[left]);break;}}else{tmp = tmp + to_string(right - left);tmp.push_back(s[left]);left = right;}}s = tmp;}return s;}
    };

    提交結果:

    方法2:打表

    1≤n≤30,由于n較小,因此可以批量生成前30個外觀數列并存儲到文件中

    知識回顧

    74.【C語言】文件操作(1)

    75.【C語言】文件操作(2)

    77.【C語言】文件操作(3)

    79.【C語言】文件操作(4)

    88.【C語言】文件操作(5)

    89.【C語言】文件操作(6)

    代碼

    結果存儲在result.txt中

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
    int main()//打表
    {vector<string> arr;arr.push_back("");//占位,可以任意寫,n>0,不會訪問到table[0]arr.push_back("1");//使用方法1的代碼for (int i = 2; i <= 30; i++){string tmp;int num = 0;char ch = arr[i - 1][0];for (int j = 0; j < arr[i - 1].size(); j++){if (arr[i - 1][j] == ch)num++;else{tmp = tmp + to_string(num);tmp.push_back(ch);ch = arr[i - 1][j];num = 1;}}if (num){tmp = tmp + to_string(num);tmp.push_back(ch);}arr.push_back(tmp);}//將arr字符串寫入文件中FILE* fptr = fopen("result.txt", "w");char str1[] = "vector<string> table={";fprintf(fptr, "%s", str1);for (auto s : arr){fprintf(fptr, "\"%s\",\n",s.c_str());}fseek(fptr, -1, SEEK_CUR);//回退一個字節fprintf(fptr, "};");//覆蓋結尾的逗號fclose(fptr);
    }

    生成結果:

    之后粘貼到leetcode上:

    ?最后返回table[n]即可

    提交結果:

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/web/87553.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/web/87553.shtml
    英文地址,請注明出處:http://en.pswp.cn/web/87553.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    Flink MySQL CDC 環境配置與驗證

    一、MySQL 服務器配置詳解 1. 啟用二進制日志&#xff08;Binlog&#xff09; MySQL CDC 依賴二進制日志獲取增量數據&#xff0c;需在 MySQL 配置文件&#xff08;my.cnf 或 my.ini&#xff09;中添加以下配置&#xff1a; # 啟用二進制日志 log-binmysql-bin # 二進制日志…

    如何查看自己電腦的CUDA版本?

    在搜索欄輸入命令提示符 打開 輸入 nvidia-smi圖片中的兩個是CUDA版本和顯卡的信息

    opencv使用 GStreamer 硬解碼和 CUDA 加速的方案

    在Conda環境中從源代碼編譯OpenCV&#xff08;支持CUDA和GStreamer&#xff09; 以下是完整的方案步驟&#xff0c;包括必要的依賴庫安裝過程&#xff1a; 1. 安裝Miniconda&#xff08;如果尚未安裝&#xff09; # 下載Miniconda安裝腳本 wget https://repo.anaconda.com/m…

    Java面試寶典:多線程一

    1. run() vs start() 陷阱題 下面程序的運行結果 public static void main(String[] args) {Thread t = new Thread(

    【CSS-14-基礎樣式表Base.css】如何編寫高質量的Base.css:前端樣式重置與基礎規范指南

    在前端開發中&#xff0c;Base.css&#xff08;也稱為重置樣式表或基礎樣式表&#xff09;是整個項目樣式的基石。它負責消除瀏覽器默認樣式的差異&#xff0c;建立統一的樣式基準&#xff0c;為后續開發提供一致的起點。一個精心設計的Base.css能夠顯著提高開發效率&#xff0…

    探索Python數據科學工具鏈NumPyPandas與Scikit-learn

    NumPy&#xff1a;數值計算的基石 NumPy是Python中用于科學計算的核心庫&#xff0c;它提供了一個強大的N維數組對象&#xff0c;以及大量的數學函數庫&#xff0c;能夠高效地進行向量和矩陣運算。對于數據科學家而言&#xff0c;掌握NumPy是進行數據處理和算法實現的基礎。 創…

    八股學習(三)---MySQL

    一、MySQL中的回表是什么&#xff1f;我的回答&#xff1a;MySQL回表指的是在查詢使用非聚簇索引也就是二級索引時&#xff0c;葉子節點只存儲了索引列的值和主鍵Id&#xff0c;若要查詢其他字段&#xff0c;就要根據主鍵去聚簇索引查詢完整的數據。這個過程就是回表。比如用na…

    NeighborGeo:基于鄰居的IP地理定位(一)

    NeighborGeo:基于neighbors的IP地理定位 X. Wang, D. Zhao, X. Liu, Z. Zhang, T. Zhao, NeighborGeo: IP geolocation based on neighbors, Comput. Netw. 257 (2025) 110896, Abstract IP地址定位在網絡安全、電子商務、社交媒體等領域至關重要。當前主流的圖神經網絡方法…

    MySQL 8.0:窗口函數

    一、基礎知識 定義 窗口函數&#xff08;Window Function&#xff09;對查詢結果集的子集&#xff08;“窗口”&#xff09;進行計算&#xff0c;保留原始行而非聚合為單行&#xff0c;適合復雜分析&#xff08;如排名、累積和&#xff09;。 基本語法&#xff1a; 函數名() OV…

    AI 深度學習面試題學習

    1.神經網絡 1.1各個激活函數的優缺點? 1.2為什么ReLU常用于神經網絡的激活函數? 1.在前向傳播和反向傳播過程中,ReLU相比于Sigmoid等激活函數計算量小; 2.避免梯度消失問題。對于深層網絡,Sigmoid函數反向傳播時,很容易就會出現梯度消失問題(在Sigmoid接近飽和區時,變換…

    遇到該問題:kex_exchange_identification: read: Connection reset`的解決辦法

    kex_exchange_identification: read: Connection reset 是一個非常常見的 SSH 連接錯誤。它表明在 SSH 客戶端和服務器建立安全連接的初始階段&#xff08;密鑰交換&#xff0c;Key Exchange&#xff09;&#xff0c;連接就被對方&#xff08;服務器&#xff09;強制關閉了。 …

    (論文蒸餾)語言模型中的多模態思維鏈推理

    &#xff08;論文總結&#xff09;語言模型中的多模態思維鏈推理 論文名稱研究背景動機主要貢獻研究細節兩階段框架實驗結果促進收斂性擺脫人工標注錯誤分析與未來前景 論文名稱 Multimodal Chain-of-Thought Reasoning in Language Models http://arxiv.org/abs/2302.00923 …

    React Native 接入 eCharts

    React Native 圖表接入指南 概述 本文檔詳細介紹了在React Native項目中接入ECharts圖表的完整步驟&#xff0c;包括依賴安裝、組件配置、數據獲取、圖表渲染等各個環節。 目錄 1. 環境準備2. 依賴安裝3. 圖表組件創建4. 數據獲取Hook5. 圖表配置6. 組件集成7. 國際化支持8…

    基于C#的OPCServer應用開發,引用WtOPCSvr.dll

    操作流程&#xff1a; 1.引入WtOPCSvr.dll文件 2.注冊服務&#xff1a;使用UpdateRegistry方法注冊&#xff0c;注意關閉應用時使用UnregisterServer取消注冊。 3.初始化服務&#xff1a;使用InitWTOPCsvr初始化 4.使用CreateTag方法&#xff0c;創建標簽 5.讀寫參數使用下面三…

    Java類加載器getResource行為簡單分析

    今天嘗試集成一個第三方SDK&#xff0c;在IDE里運行正常&#xff0c;放到服務器上卻遇到了NPE&#xff0c;反編譯一看&#xff0c;原來在這一行&#xff1a;String path Test.class.getClassLoader().getResource("").getPath(); // Test.class.getClassLoader().ge…

    【CodeTop】每日練習 2025.7.4

    Leetcode 1143. 最長公共子序列 動態規劃解決&#xff0c;比較當前位置目標和實際字符串的字母&#xff0c;再根據不同情況計算接下來的情形。 class Solution {public int longestCommonSubsequence(String text1, String text2) {char[] t1 text1.toCharArray();char[] t2…

    ES6從入門到精通:Promise與異步

    Promise 基礎概念Promise 是 JavaScript 中處理異步操作的一種對象&#xff0c;代表一個異步操作的最終完成或失敗及其結果值。它有三種狀態&#xff1a;Pending&#xff08;進行中&#xff09;、Fulfilled&#xff08;已成功&#xff09;、Rejected&#xff08;已失敗&#xf…

    數據結構:二維數組(2D Arrays)

    目錄 什么是二維數組&#xff1f; 二維數組的聲明方式 方式 1&#xff1a;靜態二維數組 方式 2&#xff1a;數組指針數組&#xff08;數組中存放的是指針&#xff09; 方式 3&#xff1a;雙指針 二級堆分配 &#x1f4a1; 補充建議 如何用“第一性原理”去推導出 C 中…

    HAProxy 和 Nginx的區別

    HAProxy 和 Nginx 都是優秀的負載均衡工具&#xff0c;但它們在設計目標、適用場景和功能特性上有顯著區別。以下是兩者的詳細對比&#xff1a;1. 核心定位特性HAProxyNginx主要角色專業的負載均衡器/代理Web 服務器 反向代理/負載均衡設計初衷高性能流量分發高并發 HTTP 服務…

    基于Java+SpringBoot的健身房管理系統

    源碼編號&#xff1a;S586源碼名稱&#xff1a;基于SpringBoot的健身房管理系統用戶類型&#xff1a;多角色&#xff0c;用戶、教練、管理員數據庫表數量&#xff1a;13 張表主要技術&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven運行環境&#xff1a;Windows/Mac、JD…