日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode 06Z字形变换07整数反转

發布時間:2025/3/20 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode 06Z字形变换07整数反转 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • Z字形變換
      • 題意
      • 分析
    • 整數反轉
    • 結語

Z字形變換

題意

題目描述

將一個給定字符串根據給定的行數,以從上往下、從左到右進行 Z 字形排列。
比如輸入字符串為 “LEETCODEISHIRING” 行數為 3 時,排列如下:

L C I R E T O E S I I G E D H N

之后,你的輸出需要從左往右逐行讀取,產生出一個新的字符串,比如:“LCIRETOESIIGEDHN”。
請你實現這個將字符串進行指定行數變換的函數:
string convert(string s, int numRows);

示例 1:

輸入: s = “LEETCODEISHIRING”, numRows = 3
輸出: “LCIRETOESIIGEDHN”

示例 2:

輸入: s = “LEETCODEISHIRING”, numRows = 4
輸出: “LDREOEIIECIHNTSG”
解釋:

L D R E O E I I E C I H N T S G

分析

對于這題該如何處理呢?首先要理解題意,它就是本來給一個字符串,然后要按照Z字形排列等到一個形狀,根據這個形狀按照從左往右的順序取值得到一個新的字符串。

法一模擬法:
既然這個字符串是固定的,那么我們是否可以模擬這個過程?

  • of course you can 模擬。你可以定義一個二位數組,根據Z字形的這個排列規律,先向下(同時橫坐標不變),再向上(同時考慮橫坐標增加)一直到最后,然后對二維數組進行遍歷取值(不空的值。)

這樣當然可以,但是模擬真的有必要這么搞嘛?當然沒必要。二維數組占據太多無用的空間浪費內存。我們其實可以對內存進行優化考慮:


這樣只需要考慮上下兩個方向往集合中添加元素,最終就可以實現啦。不過在字符串疊加時候盡量不要使用String直接加,會很慢。這種方法只能干掉40%的人,一般般。
ac代碼為:

public String convert(String s, int numRows) {List<Character> list[]=new ArrayList[numRows];for(int i=0;i<numRows;i++){list[i]=new ArrayList<Character>();}int index=0;boolean up=false;//方向 初始向下for(int i=0;i<s.length();i++){list[index].add(s.charAt(i));if(numRows==1) {continue;}if(up)//向上{if(index==0){index++;up=false;}else {index--;}}else {if(index==numRows-1){index--;up=true;}else {index++;}}}StringBuilder builder=new StringBuilder();for(int i=0;i<numRows;i++){for(int j=0;j<list[i].size();j++){builder.append(list[i].get(j));}}return builder.toString(); }

法二數學分析
上面的一種方法為模擬Z字形操作的整個流程,需要往里添加,取值也需要遍歷取值。我們能不能用另一種角度去思考問題呢?

因為每次只加一個字符,我們如果按照以下的思路看待這個問題(原字符串彎曲),從每一層看,能不能找到每一層有什么規律呢?

  • 第一層是 0 6 12也就是 0 0+(n-1)*2 0+(n-1)*3
  • 第二層兩個求位置關系,可不可以看成第一層每個位置-1和+1兩個位置(越界不考慮)?
  • 第三層和第二層同理,看成第一層的-2和+2不越界的位置。
  • 最后一層單獨考慮

這樣整個邏輯分析就完成了,可以根據位置添加元素進去再取值。ac的代碼如下:

public String convert(String s, int numRows) {if(numRows==1)return s;List<Character> list[]=new ArrayList[numRows];for(int i=0;i<numRows;i++){list[i]=new ArrayList<Character>();}//處理第一行最后一行for(int i=0;i<s.length();i+=(numRows-1)*2){list[0].add(s.charAt(i));if(i+numRows-1<s.length()){list[numRows-1].add(s.charAt(i+numRows-1));}}for(int i=0;i<s.length()+numRows;i+=(numRows-1)*2){for(int j=1;j<numRows-1;j++)//中間所有行{int index1=i-j;int index2=i+j;if(index1>=0&&index1<s.length())list[j].add(s.charAt(index1));if(index2>=0&&index2<s.length())list[j].add(s.charAt(index2));}}StringBuilder builder=new StringBuilder(); for(int i=0;i<numRows;i++){for(int j=0;j<list[i].size();j++){builder.append(list[i].get(j));}}return builder.toString();}

但這種方法也只能干掉40%+的人,該如何優化呢?

  • 首先,該方法先存到List[]再取,其實是遍歷兩次,其實大可不必這樣,我們可以在進行計算每一層的同時加入到結果中。
  • 其次,由于邊界的問題我們需要考慮太多的邊界問題,我們對此對中間層的考慮優化,兩個節點位置通過計算這樣組合,可以優化邊界的if else判斷。

注意一些細節情況,最終ac的代碼為:

public static String convert2(String s, int numRows) {if(numRows==1)return s;//處理第一行StringBuilder builder=new StringBuilder();for(int i=0;i<s.length();i+=(numRows-1)*2){builder.append(s.charAt(i));}for(int i=1;i<numRows-1;i++){for(int j=0;j<s.length()+numRows;j+=(numRows-1)*2)//中間所有行{int index1=j+i;int index2=j+(numRows-1)*2-i;if(index1<s.length())builder.append(s.charAt(index1));if(index2<s.length())builder.append(s.charAt(index2));}}for(int i=numRows-1;i<s.length();i+=(numRows-1)*2){ builder.append(s.charAt(i));}return builder.toString();}

最終的效果還行(偶爾三毫秒):

整數反轉

這題的話注意以下數組越界問題,可以用long類型處理最終再用整形處理。

主要有兩種處理方法,一個就是轉成字符串處理,第二個就是用數值處理。但是一般盡量不要用字符串處理比較慢。

ac代碼為:

public int reverse(int x) {if(x==0)return 0;String value=x+"";if(value.charAt(0)=='-')value=value.substring(1);StringBuilder sb=new StringBuilder();for(int i=value.length()-1;i>=0;i--){sb.append(value.charAt(i));}long num=Long.parseLong(sb.toString());if(x<0)num=-num;if(num<Integer.MIN_VALUE||num>Integer.MAX_VALUE){return 0;}return (int)num;}

數值類型處理方式為:

public int reverse(int x) {if(x==0)return 0;long num=0;while (x%10==0) {x/=10;}int t;while (x!=0) {t=x%10;//各位num=num*10+t;x/=10;if(num>Integer.MAX_VALUE||num<Integer.MIN_VALUE)return 0;}return (int)num; }

時間還行:

結語

本次兩題稍容易一些,再接再厲,注意方法的優化。

歡迎關注公眾號:bigsai,回復進群,一起打卡LeetCode!

總結

以上是生活随笔為你收集整理的LeetCode 06Z字形变换07整数反转的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。