自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

20200202 這個千年一遇的對稱日,是時候?qū)ⅰ富匚乃惴ā挂痪W(wǎng)打盡!

大數(shù)據(jù) 數(shù)據(jù)可視化 算法
20200202 這種正反都一樣的串,在算法上稱為「回文」,又因為不同的結(jié)構(gòu),被分為回文數(shù)、回文字符串、回文鏈表等。

[[313923]]

  今天是 2020 年 02 月 02 日,被稱為「千年一遇的對稱日」,20200202 正反都一樣,反正都是「愛你愛你」的意思。不少新人都選擇今天作為領(lǐng)證的日子,不過因為肺炎的緣故,有些地方已經(jīng)取消了今日的預約。 

但是我們今天不聊這日子的寓意,我們來聊聊技術(shù)相關(guān)的話題。

20200202 這種正反都一樣的串,在算法上稱為「回文」,又因為不同的結(jié)構(gòu),被分為回文數(shù)、回文字符串、回文鏈表等。

這分別又延伸出好幾個 Leetcode 算法題,今天我們在這個別人領(lǐng)證的日子,復習一下「回文」相關(guān)的算法題。

一. 驗證回文字符串

今天的日期,用字符串表示是 "20200202",這就是一個回文字符串。

那么想要寫個方法,驗證其是否是一個回文字符串,拍腦袋想最簡單的方法就是將字符串翻轉(zhuǎn)后比對。 

  1. boolean isPalindrome(String s) { 
  2.   return new StringBuilder(s).reverse().equals(s) 

 

但是多數(shù)情況下是不允許我們直接使用 Api,那除此之外,比較常用的方法就是用 2 個指針,從字符串的前后兩個方向,向內(nèi)夾。

  1. boolean isPalindrome(String s) { 
  2.     int i = 0; 
  3.   int j = s.length() - 1; 
  4.   while (i < j ) { 
  5.     if (Character.toLowerCase(s.charAt(i) != Character.toLowerCase(s.charAt(j))) { 
  6.         return false
  7.     } 
  8.     i++; 
  9.     j--; 
  10.   } 
  11.   return true

邏輯很簡單,一個循環(huán)兩個指針,就搞定了。

但是因為這是一個字符串,很輕易的可以拿到字符串的長度,所以一般算法題會加上一些額外的條件,增加難度。

例如 Leetcode 上的「125. 驗證回文串」,給定的字符串是包含空格的。 

 這種情況呢,只需要把之前的解法改改就好了,兩個指針在移動的時候,如果遇上 1 個空格就多走 1 步即可。 

  1. public boolean isPalindrome(String s) { 
  2.   int i = 0, j = s.length() - 1; 
  3.   while(i < j){ 
  4.     while(i < j && !Character.isLetterOrDigit(s.charAt(i))) 
  5.       i++; 
  6.     while(i < j && !Character.isLetterOrDigit(s.charAt(j))) 
  7.       j--; 
  8.     if(Character.toLowerCase(s.charAt(i)) != 
  9.        Character.toLowerCase(s.charAt(j))) 
  10.       return false
  11.     i++; j--; 
  12.   } 
  13.   return true

通過 isLetterOrDigit() 可以直接判斷當前字符是不是只屬于字母和數(shù)字。

關(guān)于字符串的回文算法,除了 125 之外,leetcode 第 680 題也屬于回文字符串,有興趣可以去看看。

二. 驗證回文數(shù)

如果回文字符串中只包含數(shù)字,那么它也可以是一個回文數(shù),例如 20200202。

想要驗證回文數(shù),比較簡單的方法就是將其轉(zhuǎn)換字符串,然后用驗證字符回文串的算法模式去套用。但是這并沒有用到數(shù)字的特性。

既然是數(shù)字,我們可以通過除法 / 和取余 % 的方式,將這個數(shù)字取出后半段進行翻轉(zhuǎn),然后比對兩個數(shù)字的是否相等。

  1. public boolean isPalindrome(int x) { 
  2.   if (x < 0 || (x % 10 == 0 && x != 0)) 
  3.     return false
  4.   int revertedNumber = 0; 
  5.   while (x > revertedNumber) { 
  6.     revertedNumber = revertedNumber * 10 + x % 10; 
  7.     x /= 10; 
  8.   } 
  9.   return x == revertedNumber || x == revertedNumber / 10; 

 簡單解釋一下:

1. 首先做一些簡單的驗證。如果一個大于 0 的非零數(shù),個位為 0 ,那么它注定不是一個回文數(shù)。因為對應的回文位置是這個數(shù)字的最高位,而最高位不會為 0。

2. 通過循環(huán),每次循環(huán)中,按位生成翻轉(zhuǎn)后的數(shù)字,并將原數(shù)字最低位打掉。

3. 如果跳出循環(huán),說明后半部分已經(jīng)翻轉(zhuǎn)完畢,那么分兩個情況考慮,數(shù)字長度是奇數(shù)還是偶數(shù)。然后判斷原數(shù)字 x 和后半部分翻轉(zhuǎn)的數(shù)字 reversedNumber 是否相同。

另外提一句,這道題是 Leetcode 上的「9. 回文數(shù)」題。

三. 驗證回文鏈表

回文串和回文數(shù)都說了,接下來看看回文鏈表。

單鏈表這種特殊的結(jié)構(gòu),想要確定個長度也需要 O(n) 的復雜度,而且沒有前驅(qū)指針,雙指針前后夾的辦法是沒法用了。

當然我們可以將它轉(zhuǎn)換為我們熟悉的回文數(shù)或者回文串進行計算,但是這同樣沒有用到鏈表的特性。

在驗證回文鏈表的場景下,我們可以通過快慢指針的方式找到鏈表的中間節(jié)點,然后再將原鏈表的一半反轉(zhuǎn),之后開始比對。

為了效率,可以把這兩個步驟糅合在 1 個循環(huán)中。

  1. public boolean isPalindrome(ListNode head) { 
  2.   if(head == null || head.next == null) { 
  3.     return true
  4.   } 
  5.   ListNode slow = head, fast = head; 
  6.   ListNode pre = head, prepre = null
  7.   while(fast != null && fast.next != null) { 
  8.     pre = slow; 
  9.     slow = slow.next
  10.     fast = fast.next.next
  11.     pre.next = prepre; 
  12.     prepre = pre; 
  13.   } 
  14.   // 如果 fast 不為 null,說明是奇數(shù),需要再進一位 
  15.   if(fast != null) { 
  16.     slow = slow.next
  17.   } 
  18.   // 此時 pre 為反轉(zhuǎn)原鏈表前半部分的子鏈表 
  19.   // slow 為原鏈表的中間節(jié)點 
  20.   while(pre != null && slow != null) { 
  21.     if(pre.val != slow.val) { 
  22.       return false
  23.     } 
  24.     pre = pre.next
  25.     slow = slow.next
  26.   } 
  27.   return true

 第一遍循環(huán)之后,slow 節(jié)點指向了鏈表的中間位置,而 pre 則是翻轉(zhuǎn)了原鏈表的前半部分的子鏈表。

再通過一個 while 循環(huán),將它們逐個比對,就可以得到我們要的結(jié)果。

另外提一句,這道題是 Leetcode 上的「234. 回文鏈表」題。

四. 小結(jié)時刻

那今天就到這里,20200202 這個日子里,我們復習了一下回文相關(guān)的算法題,不知道分別從字符串、數(shù)字、鏈表三個方向橫向的看回文類的題之后,你能總結(jié)出什么規(guī)律?歡迎在留言區(qū)討論。

因為疫情的緣故,不少朋友明日起,就要切換到在家遠程辦公狀態(tài)了,祝各位順利。

 

責任編輯:武曉燕 來源: 承香墨影
相關(guān)推薦

2024-04-26 00:25:52

Rust語法生命周期

2010-08-25 01:59:00

2021-08-05 06:54:05

流程控制default

2021-10-11 07:55:42

瀏覽器語法Webpack

2024-02-27 10:11:36

前端CSS@規(guī)則

2013-08-02 10:52:10

Android UI控件

2024-04-07 08:41:34

2024-08-26 10:01:50

2024-06-12 00:00:05

2011-12-02 09:22:23

網(wǎng)絡(luò)管理NetQos

2019-10-17 09:26:34

IDC資訊機房

2019-07-24 15:30:00

SQL注入數(shù)據(jù)庫

2020-02-21 08:45:45

PythonWeb開發(fā)框架

2023-04-06 09:08:41

BPM流程引擎

2013-10-16 14:18:02

工具圖像處理

2021-05-20 11:17:49

加密貨幣區(qū)塊鏈印度

2023-09-06 18:37:45

CSS選擇器符號

2021-10-29 09:32:33

springboot 靜態(tài)變量項目

2023-04-03 08:30:54

項目源碼操作流程

2020-10-19 06:43:53

Redis腳本原子
點贊
收藏

51CTO技術(shù)棧公眾號