github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/leetcode.go (about)

     1  package util
     2  
     3  import (
     4  	"math"
     5  )
     6  
     7  // Max for int
     8  func Max(a, b int) int {
     9  	if a > b {
    10  		return a
    11  	}
    12  
    13  	return b
    14  }
    15  
    16  // Min for int
    17  func Min(a, b int) int {
    18  	if a > b {
    19  		return b
    20  	}
    21  
    22  	return a
    23  }
    24  
    25  // MaxLengthOfUniqueSubstring returns the max length of unique sub string
    26  func MaxLengthOfUniqueSubstring(s string) (l int) {
    27  
    28  	var indexes [math.MaxUint8] /*byte是uint8*/ int
    29  	n := len(s)
    30  
    31  	var i, j int
    32  	// 基于的观察:
    33  	// 如果s[j]跟[i,j)有重复j',那么可以跳过[i,j']的元素,i直接变为j'+1
    34  	for ; j < n; j++ {
    35  		byteJ := s[j]
    36  		// 假如indexes的元素非0,那么必定是这个byte上一次出现的位置j'+1
    37  		// 且j'的位置必须在[i,j)之间才有效
    38  		if indexes[byteJ] != 0 && indexes[byteJ] > i {
    39  			i = indexes[byteJ]
    40  		}
    41  
    42  		l = Max(l, j-i+1)
    43  		indexes[byteJ] = j + 1
    44  	}
    45  	return
    46  }
    47  
    48  // ManacherFallback when all byte values are used in s
    49  func ManacherFallback(s string) (ss string) {
    50  	n := len(s)
    51  
    52  	for i := 0; i < n; i++ {
    53  		// 奇数的情况
    54  		j := 1
    55  		for ; i-j >= 0 && i+j < n; j++ {
    56  			if s[i-j] != s[i+j] {
    57  				break
    58  			}
    59  		}
    60  		if len(ss) < (j*2 - 1) {
    61  			ss = s[i-j+1 : i+j]
    62  		}
    63  		// 偶数的情况
    64  		if i+1 < n && s[i] == s[i+1] {
    65  			j := 1
    66  			for ; i-j >= 0 && i+1+j < n; j++ {
    67  				if s[i-j] != s[i+1+j] {
    68  					break
    69  				}
    70  			}
    71  			if len(ss) < j*2 {
    72  				ss = s[i-j+1 : i+j+1]
    73  			}
    74  		}
    75  	}
    76  	return
    77  }
    78  
    79  // ManacherWithFallback tries Manacher if possible
    80  func ManacherWithFallback(s string) (ss string) {
    81  	var indexes [math.MaxUint8] /*byte是uint8*/ bool
    82  	n := len(s)
    83  	for i := 0; i < n; i++ {
    84  		indexes[s[i]] = true
    85  	}
    86  	canManacher := false
    87  	var manacherByte byte
    88  	for i, exists := range indexes {
    89  		if !exists {
    90  			canManacher = true
    91  			manacherByte = byte(i)
    92  			break
    93  		}
    94  	}
    95  	if !canManacher {
    96  		ss = ManacherFallback(s)
    97  		return
    98  	}
    99  
   100  	// preprocess
   101  	bytes := make([]byte, 2*n+1, 2*n+1)
   102  	bytes[0] = manacherByte
   103  	for i := 0; i < n; i++ {
   104  		bytes[2*i+1] = s[i]
   105  		bytes[2*i+2] = manacherByte
   106  	}
   107  
   108  	r := make([]int, 2*n+1)
   109  	var maxRightPos, maxRight, maxRPos, maxR int
   110  	r[0] = 1
   111  	r[2*n] = 1
   112  	for i := 1; i < 2*n; i++ {
   113  		if i >= maxRight {
   114  			// 半径包括自己,所以1是最小值
   115  			r[i] = 1
   116  		} else {
   117  			// i在maxRight以内
   118  			// j'坐标为2*maxRightPos-i
   119  			r[i] = Min(maxRight-i, r[2*maxRightPos-i])
   120  		}
   121  		// 尝试扩大半径
   122  		for {
   123  			if i-r[i] >= 0 && i+r[i] <= 2*n && bytes[i-r[i]] == bytes[i+r[i]] {
   124  				r[i]++
   125  			} else {
   126  				break
   127  			}
   128  		}
   129  		if i+r[i]-1 > maxRight {
   130  			maxRight = i + r[i] - 1
   131  			maxRightPos = i
   132  		}
   133  		if maxR < r[i] {
   134  			maxRPos = i
   135  			maxR = r[i]
   136  		}
   137  	}
   138  
   139  	targetBytes := make([]byte, 0, r[maxRPos]-1 /*最终结果的长度*/)
   140  	for i := maxRPos - r[maxRPos] + 1; i < maxRPos+r[maxRPos]; i++ {
   141  		if bytes[i] != manacherByte {
   142  			targetBytes = append(targetBytes, bytes[i])
   143  		}
   144  	}
   145  
   146  	ss = String(targetBytes)
   147  	if len(ss) != r[maxRPos]-1 {
   148  		panic("size != r[maxRPos]-1")
   149  	}
   150  
   151  	return
   152  }
   153  
   154  // ReverseDigits for reverse digits
   155  func ReverseDigits(n int32) (r int32) {
   156  
   157  	if n > 0 {
   158  		for n != 0 {
   159  			pop := n % 10
   160  			// 溢出判断
   161  			if (r > math.MaxInt32/10) || (r == math.MaxInt32/10 && pop > 7) {
   162  				// 上溢出
   163  				return 0
   164  			}
   165  
   166  			r = 10*r + pop
   167  			n /= 10
   168  		}
   169  	} else {
   170  		for n != 0 {
   171  			pop := n % 10
   172  			// 溢出判断
   173  			if r < math.MinInt32/10 || (r == math.MinInt32/10 && pop < -8) {
   174  				// 下溢出
   175  				return 0
   176  			}
   177  
   178  			r = 10*r + pop
   179  			n /= 10
   180  		}
   181  	}
   182  
   183  	return
   184  }
   185  
   186  // IsPalindrome checks whether n is palindrome
   187  func IsPalindrome(n int) bool {
   188  	if n < 0 {
   189  		return false
   190  	}
   191  
   192  	var reverted int
   193  	// 反转一半即可
   194  	for n > reverted {
   195  		reverted = 10*reverted + n%10
   196  		n /= 10
   197  	}
   198  
   199  	return reverted == n || reverted/10 == n
   200  }
   201  
   202  // PatternMatchAllTD matches p against the whole s
   203  // pattern supprts . and *
   204  // top down
   205  func PatternMatchAllTD(s, p string) bool {
   206  
   207  	slen := len(s)
   208  	plen := len(p)
   209  	if plen == 0 {
   210  		return slen == 0
   211  	}
   212  
   213  	memo := make([][]*bool, slen)
   214  	for i := 0; i < slen; i++ {
   215  		memo[i] = make([]*bool, plen)
   216  	}
   217  
   218  	var subProbFunc func(i, j int) bool
   219  	// 子问题函数
   220  	subProbFunc = func(i, j int) bool {
   221  
   222  		// 如果都越界,匹配成功
   223  		if i >= slen && j >= plen {
   224  			return true
   225  		}
   226  		// 只有p越界,匹配失败
   227  		if j >= plen {
   228  			return false
   229  		}
   230  		// i越界,p未越界
   231  		if i >= slen {
   232  			// 看p能否匹配空
   233  			if j+1 >= plen {
   234  				return false
   235  			}
   236  			if p[j+1] != '*' {
   237  				return false
   238  			}
   239  			return subProbFunc(i, j+2)
   240  		}
   241  
   242  		// 如果已计算,直接返回结果
   243  		if memo[i][j] != nil {
   244  			return *memo[i][j]
   245  		}
   246  
   247  		match := s[i] == p[j] || p[j] == '.'
   248  		if j+1 >= plen {
   249  			result := match && i == slen-1
   250  			memo[i][j] = &result
   251  			return result
   252  		}
   253  
   254  		// 转移方程
   255  
   256  		if p[j+1] == '*' {
   257  			result := subProbFunc(i, j+2) || // 匹配0次
   258  				(match && subProbFunc(i+1, j+2)) || // 匹配1次
   259  				(match && subProbFunc(i+1, j)) // 匹配多次
   260  
   261  			memo[i][j] = &result
   262  			return result
   263  		}
   264  
   265  		result := match && subProbFunc(i+1, j+1)
   266  		memo[i][j] = &result
   267  
   268  		return result
   269  	}
   270  
   271  	return subProbFunc(0, 0)
   272  }
   273  
   274  // PatternMatchAllBU matches p against the whole s
   275  // pattern supprts . and *
   276  // bottom up
   277  func PatternMatchAllBU(s, p string) bool {
   278  
   279  	slen := len(s)
   280  	plen := len(p)
   281  	if plen == 0 {
   282  		return slen == 0
   283  	}
   284  
   285  	memo := make([][]*bool, slen)
   286  	for i := 0; i < slen; i++ {
   287  		memo[i] = make([]*bool, plen)
   288  	}
   289  
   290  	var subProbFunc func(i, j int) bool
   291  	subProbFunc = func(i, j int) bool {
   292  		if i < 0 && j < 0 {
   293  			return true
   294  		}
   295  		if j < 0 {
   296  			return false
   297  		}
   298  		if i < 0 {
   299  			// 看p能否匹配空
   300  			if p[j] != '*' {
   301  				return false
   302  			}
   303  			if j == 0 {
   304  				return false
   305  			}
   306  			return subProbFunc(i, j-2)
   307  		}
   308  
   309  		// 如果已计算,直接返回结果
   310  		if memo[i][j] != nil {
   311  			return *memo[i][j]
   312  		}
   313  
   314  		match := s[i] == p[j] || p[j] == '.'
   315  		if j == 0 {
   316  			result := match && i == 0
   317  			memo[i][j] = &result
   318  			return result
   319  		}
   320  
   321  		if p[j] == '*' {
   322  			result := subProbFunc(i, j-2) || /*匹配0次*/
   323  				((p[j-1] == s[i] || p[j-1] == '.') &&
   324  					(subProbFunc(i-1, j-2) || /*匹配1次*/
   325  						subProbFunc(i-1, j))) /*匹配多次*/
   326  			memo[i][j] = &result
   327  			return result
   328  		}
   329  
   330  		result := match && subProbFunc(i-1, j-1)
   331  		memo[i][j] = &result
   332  		return result
   333  	}
   334  
   335  	return subProbFunc(slen-1, plen-1)
   336  }
   337  
   338  // PatternMatchAllRec is the recursive version for PatternMatchAll
   339  func PatternMatchAllRec(s, p string) bool {
   340  	if len(p) == 0 {
   341  		return len(s) == 0
   342  	}
   343  
   344  	if len(s) == 0 {
   345  		// p必须是x*y*这种
   346  		if len(p) < 2 || p[1] != '*' {
   347  			return false
   348  		}
   349  		return PatternMatchAllRec(s, p[2:])
   350  	}
   351  
   352  	match := s[0] == p[0] || p[0] == '.'
   353  	if len(p) < 2 {
   354  		return match && len(s) == 1
   355  	}
   356  
   357  	if p[1] == '*' {
   358  		return PatternMatchAllRec(s, p[2:]) /*匹配0次*/ ||
   359  			(match && PatternMatchAllRec(s[1:], p[2:])) /*匹配1次*/ ||
   360  			(match && PatternMatchAllRec(s[1:], p)) /*匹配多次*/
   361  	}
   362  
   363  	return match && PatternMatchAllRec(s[1:], p[1:])
   364  
   365  }
   366  
   367  // FindOnceNum find the number that appears only once
   368  // caller should make sure only one num appears once
   369  func FindOnceNum(nums []int) (r int) {
   370  	for _, n := range nums {
   371  		r ^= n
   372  	}
   373  	return
   374  }
   375  
   376  // MinCoveringSubstr finds min substr of s that covers t
   377  func MinCoveringSubstr(s, t string) (ss string) {
   378  
   379  	// 双指针滑动窗口
   380  	var left, right, matched int
   381  
   382  	needed := make(map[byte]int)
   383  	for i := 0; i < len(t); i++ {
   384  		needed[t[i]]++
   385  	}
   386  	windowed := make(map[byte]int)
   387  	minLen := len(s) + 1
   388  
   389  	for right < len(s) {
   390  
   391  		rb := s[right]
   392  		if _, ok := needed[rb]; ok {
   393  			windowed[rb]++
   394  			if windowed[rb] == needed[rb] {
   395  				matched++
   396  			}
   397  		}
   398  
   399  		if matched == len(needed) {
   400  			for {
   401  				lb := s[left]
   402  				if _, ok := needed[lb]; !ok {
   403  					left++
   404  					continue
   405  				}
   406  				if windowed[lb] > needed[lb] {
   407  					left++
   408  					windowed[lb]--
   409  					continue
   410  				}
   411  				// left不能再右了
   412  				if right-left+1 < minLen {
   413  					ss = s[left : right+1]
   414  					minLen = right - left + 1
   415  				}
   416  				left++
   417  				windowed[lb]--
   418  				matched--
   419  				break
   420  			}
   421  		}
   422  
   423  		right++
   424  	}
   425  
   426  	return
   427  }
   428  
   429  // LongestConsecutive finds longest consecutive in nums
   430  func LongestConsecutive(nums []int) (sn, length int) {
   431  	numMap := make(map[int]struct{})
   432  	for _, n := range nums {
   433  		numMap[n] = struct{}{}
   434  	}
   435  
   436  	for _, n := range nums {
   437  		if _, ok := numMap[n-1]; ok {
   438  			continue
   439  		}
   440  		nn := n + 1
   441  		for {
   442  			if _, ok := numMap[nn]; ok {
   443  				nn++
   444  			} else {
   445  				if nn-n > length {
   446  					length = nn - n
   447  					sn = n
   448  				}
   449  				break
   450  			}
   451  		}
   452  	}
   453  
   454  	return
   455  }