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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

LeetCode_脑筋急转弯

發布時間:2025/3/8 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode_脑筋急转弯 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄:

  • 292.Nim游戲
  • 319.燈泡開關
  • 777.在LR字符串中叫喚相鄰字符
  • 1033.移動石子直到連續
  • 1227.飛機座位分配率
  • 1503.所有螞蟻掉下來前的最后一刻

292.Nim游戲

思路

如果堆中石頭的數量 nn 不能被 44 整除,那么你總是可以贏得 Nim 游戲的勝利。

推理

讓我們考慮一些小例子。顯而易見的是,如果石頭堆中只有一塊、兩塊、或是三塊石頭,那么在你的回合,你就可以把全部石子拿走,從而在游戲中取勝。而如果就像題目描述那樣,堆中恰好有四塊石頭,你就會失敗。因為在這種情況下不管你取走多少石頭,總會為你的對手留下幾塊,使得他可以在游戲中打敗你。因此,要想獲勝,在你的回合中,必須避免石頭堆中的石子數為 4 的情況。

同樣地,如果有五塊、六塊、或是七塊石頭,你可以控制自己拿取的石頭數,總是恰好給你的對手留下四塊石頭,使他輸掉這場比賽。但是如果石頭堆里有八塊石頭,你就不可避免地會輸掉,因為不管你從一堆石頭中挑出一塊、兩塊還是三塊,你的對手都可以選擇三塊、兩塊或一塊,以確保在再一次輪到你的時候,你會面對四塊石頭。

顯然,它以相同的模式不斷重復 n=4,8,12,16,\dotsn=4,8,12,16,…,基本可以看出是 44 的倍數。

題解C

bool canWinNim(int n){return (n/4==0); }

319.燈泡開關


1 分析
1)第j輪的第i個燈泡的狀態判斷方法:
將包含本輪在內的對第i個燈泡的所有操作次數做和,記為Sij。
若Sij為奇數,說明第i個燈泡,經過j輪以后,是亮著的,因為第0輪一定是關閉的。
同理,若Sij為偶數,說明第i個燈泡,經過j輪以后,是關閉的。

所以問題轉變為:
經過n輪,第i個燈泡被操作了奇數次還是偶數次?奇數次則最后是亮的,偶數次則最后是關閉的。

2)觀察:
第j輪操作的燈泡的位置,一定是j的倍數。咱們反向觀察一下:

第1個燈泡在什么時候會被操作?第1輪
第10個燈泡在什么時候會被操作?第1輪,第2輪,第5輪,第10輪
第20個燈泡在什么時候會被操作?第1輪,第2輪,第4輪,第5輪,第10輪,第20輪

說到這里,會立馬發現:第 i 個燈泡只有在第 k 輪會被操作,而 k 一定是 i 的因數。并且 n>=k。所以如果一個數的因數的個數為奇數個,那么它最后一定是亮的,否則是關閉的。
那么問題又轉變了:

什么數的因數的個數是奇數個?
答案是完全平方數。

2 為什么完全平方數的因數的個數是奇數個?
設P,A,B 為正整數,如果 P=A*B,則A和B為P的因數。
P的因數A和B總是成對出現。也就是說他們總是一起為 P 的因數個數做貢獻。但是如果他們相等呢?這個時候他們一起只會為因數的個數貢獻 1。

其次,P=A*A,這種情況對于P來說最多只能出現1次,而這種情況只可能出現在完全平方數中。
所以對于正整數而言,只有完全平方數的因數的個數是奇數個。

綜上所述,所以每個完全平方數就是答案

還可以這樣推導:
對于數k,第i輪被撥一下的條件是k%i==0
所有數k被撥的次數是k的約束的個數
若k=p_1^x p_2^y p_3^z … , 其中p_i為素數,則約數的個數f(k)= (1+x)(1+y)(1+z).
第k個燈亮意味著f(k)為奇數,根據推論3可知,其中的x,y,z…都必須為偶數。
回看,k=p_1^x p_2^y p_3^z … , 說明k是個完全平方數

題解C

int bulbSwitch(int n){return (int)sqrt(n); }

777.在LR字符串中叫喚相鄰字符


思路

將 ‘L’,‘R’ 分別理解為一個隊伍中面向左和面向右的人,‘X’ 理解為隊伍中的空擋。可以問自己一個問題,一次移動操作之后有什么是保持不變的? 這是狀態轉換問題中一個很常見的思路。

算法

這道題的 轉換不變性 在于字符串中的 ‘L’ 和 ‘R’ 是不會互相穿插的,也就是隊伍中的人在移動過程中是不能穿過人的。這意味著開始和結束的字符串如果只看 ‘L’ 和 ‘R’ 的話是一模一樣的。

除此之外,第 n 個 ‘L’ 不可能移動到初始位置的右邊,第 n 個 ‘R’ 不可能移動到初始位置的左邊,我們把這個特性稱為 “可到達性“。

根據 轉換不變性 和 可到達性,在算法中可以分別檢查這兩個性質是否滿足。如果都滿足,則返回 True,否則返回 False。

題解Java

class Solution {public boolean canTransform(String start, String end) {if (!start.replace("X", "").equals(end.replace("X", "")))return false;int t = 0;for (int i = 0; i < start.length(); ++i)if (start.charAt(i) == 'L') {while (end.charAt(t) != 'L') t++;if (i < t++) return false; //發現end中L往右移了}t = 0;for (int i = 0; i < start.length(); ++i)if (start.charAt(i) == 'R') {while (end.charAt(t) != 'R') t++;if (i > t++) return false; //發現end中R往左移了}return true;} }

1033.移動石子直到連續


思路:
題目看著很繞,其實很簡單,首先排序,排序并不會改變結果,但是我們寫起來更方便一點,然后重新賦值abc

a最小,c最大,因為只能拿兩邊的石頭往中間放,所以最大情況就是一步一步挪,那么就是c-a-2,最小情況多重情況討論即可

三個緊貼著 c-a=2 返回0
其中有兩個緊貼著 返回1
其中有兩個中間空了一格 返回 1
最小移動次數最大是2 就是兩邊分別往中間放

題解Java

class Solution {public int[] numMovesStones(int a, int b, int c) {int[] arr = new int[]{a, b, c};Arrays.sort(arr);a=arr[0];b=arr[1];c=arr[2];int min = 0;if (c - a == 2) min = 0;else if (b - a == 1 || c - b == 1) min = 1;else if (b - a == 2 || c - b == 2) min = 1;else min = 2;return new int[]{min, c - a - 2};} }

1227.飛機座位分配率


思路
設dp[i]為第i個乘客坐在自己的座位上的概率,
初始化dp[1]=1;dp[2]=0.5;

當i=3時:
若第一個人選擇第一個座位,后邊的人的椅子沒有被占用,按照正常順序,第3個人肯定能坐到第3個位置,這個概率是1/3;
若第一個人選擇第二個位置,第二個人發現自己的椅子被占用,他有兩個位置可選,只有選擇第一個位置,第三個人才能坐到自己的位置,根據概率乘法原則,這個概率是1/3 × 1/2;
只有這兩種情況,第3個人才能坐到第三個位置
所以dp[3]=1/3+1/3×1/2
=1/3×(1+1/2)
=1/3×(dp[1]+dp[2])

以此類推,可以推出來:
dp[i]=(1/i)×(dp[1]+dp[2]+…+dp[i-1])
這就是狀態轉移方程

所以說實際上只要n>1,那么結果必是1/2!

題解Java

class Solution {public double nthPersonGetsNthSeat(int n) {if (n == 1) {return 1.0;}double [] dp=new double[n+1];//從下標1開始使用dp[2]=0.5;double sum_dp=1.5;for(int i=3;i<=n;i++){dp[i]=(1.0/(double)i)*sum_dp;sum_dp+=dp[i];}return dp[n];} }

1503.所有螞蟻掉下來前的最后一刻

思路
兩個螞蟻相撞之后會互相調頭,其實只要想成如果每只螞蟻都長得一模一樣,那么是不是螞蟻碰撞的調頭 就等于 穿透了?

知道了這一點,那么就可以直接讓螞蟻直接穿透爬行就好了

那么題目就變成了求單只最晚落地的螞蟻,與碰撞無關

題解Java_1

class Solution {public int getLastMoment(int n, int[] left, int[] right) {int max = -1;for(int i = 0; i < left.length;i++){max = Math.max(max,left[i]);}for(int i = 0; i < right.length;i++){max = Math.max(max,n-right[i]);}return max;} }

題解Java_2

class Solution {public int getLastMoment(int n, int[] left, int[] right) {int leftMax = Integer.MIN_VALUE;int rightMin = Integer.MAX_VALUE;// 往右走的取最小值for (int item : right) {if (rightMin > item) {rightMin = item;}}// 往左走的取最大值for (int item : left) {if (leftMax < item) {leftMax = item;}}return Math.max(leftMax, n - rightMin);} }

總結

以上是生活随笔為你收集整理的LeetCode_脑筋急转弯的全部內容,希望文章能夠幫你解決所遇到的問題。

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