四數問題下邏輯運算子的注意事項
阿新 • • 發佈:2018-12-16
給定一個包含 n 個整數的陣列 nums
,判斷 nums
中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。
例如, 給定陣列 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合為:
[
[-1, 0, 1],
[-1, -1, 2]
]
public static List<List<Integer>> fourSum(int[] nums, int target) { int firs; int seco; int thir; int four; int temp; List<List<Integer>> res = new LinkedList<>(); Arrays.sort(nums); for (firs = 0; firs < nums.length; firs++) { for (seco = firs + 1; seco < nums.length; seco++) { thir = seco + 1; four = nums.length - 1; while (thir < four) { temp = nums[firs] + nums[seco] + nums[thir] + nums[four]; if (temp == target) { res.add(Arrays.asList(nums[firs], nums[seco], nums[thir], nums[four])); while (nums[thir] == nums[thir + 1] && thir < four) thir++; while (nums[four] == nums[four - 1] && thir < four) four--; thir++; four--; } else if (temp > target) { while (nums[four] == nums[four - 1] && four > thir) four--; four--; } else { while (nums[thir] == nums[thir + 1] && thir < four) thir++; thir++; } } } } return res; }
以上為第一次寫出的解決方法,具體做法是將四數之和轉換為外層迴圈加一個三數之和(而三數之和可以轉換為外層迴圈加雙指標問題)。
但是測試時,輸入陣列{0,0,0,0}與target=0,會在
while (nums[thir] == nums[thir + 1] && thir < four) thir++;
這一語句處報ArrayIndexOutOfBoundsException異常,經過debug後發現,邏輯運算子&&的左右判斷語句的順序影響了程式的正確性。
此時,thir = 3, 先進行判斷nums[thir] == nums[thir + 1],然後判斷thir < four都滿足於是 thir++,此時thir = 4,然後再次進行判斷nums[thir] == nums[thir + 1] ,此時thir + 1 = 4,於是就發生陣列下標越界的異常。
根據邏輯,每次進行比較前應先判斷是否第三個數小於第四個,所以應該將
while (nums[thir] == nums[thir + 1] && thir < four) thir++;
while (nums[four] == nums[four - 1] && thir < four) four--;
中的兩個while迴圈中的邏輯判斷順序調換一下:
while (thir < four && nums[thir] == nums[thir + 1]) thir++; while (thir < four && nums[four] == nums[four - 1]) four--;
果然調換了一下順序之後就對了,在進行陣列判斷之前,會先判斷thir < four,若thir = 4,則這時已經不滿足了,就不會進行後面的判斷。
其實程式是次要的,主要是在進行邏輯判斷的時候,一定要注意先後順序(吃了好幾次這樣的虧,特此記錄一下)。