我正在尝试为leetcode(链接:https://leetcode.com/problems/3sum/)上的3sum问题编写解决方案。
这是我到目前为止所做的:
public int binary_search(int [] nums, int start, int end, int target)
{
if (start > end)
{
return -1;
}
int mid = (start + end) / 2;
if (nums[mid] == target)
{
return mid;
}
else {
if (nums[mid] < target)
{
return binary_search(nums, mid + 1, end, target);
} else {
return binary_search(nums, start, mid - 1, target);
}
}
}
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
ArrayList<List<Integer>> solution_set = new ArrayList();
Set<List<Integer>> ordered_solutions = new HashSet();
for (int i = 0; i < nums.length; i++)
{
if (i + 1 == nums.length)
{
continue;
}
int number_1 = nums[i];
int number_2 = nums[i+1];
int target = -(number_1 + number_2);
int target_index = binary_search(nums, 0, nums.length - 1, target);
if (binary_search(nums, 0, nums.length - 1, target) != -1 && target_index != i && target_index != i+1)
{
List<Integer> submission = new ArrayList();
submission.add(number_1); submission.add(number_2); submission.add(target);
List<Integer> ordered_submission = submission;
Collections.sort(ordered_submission);
if (ordered_solutions.add(ordered_submission) == true)
{
solution_set.add(submission);
}
}
}
return solution_set;
}
该程序的工作方式如下: 输入被输入到threeSum函数,然后对它进行排序并创建两个后续对象;一个将存储所有非重复解决方案的ArrayList和一个用于测试所述重复解决方案的Set。
然后,for循环在数组中筛选并执行以下操作: 它添加了i和i + 1元素,然后取反它们,以找到将所有三个数字总和为零所需的数字。获取此数字后,对阵列进行二进制搜索以查看是否可以找到该数字。如果找到,则测试其他一些条件以确保目标索引实际上与索引i或i + 1不相同。之后,我创建了两个对象,一个包含按其原始顺序的元素的提交和一个有序的提交。如果将有序提交提交到集合中,并且集合返回true,则表示它不是重复的,我将其存储在solution_set中。
我的问题如下:我的程序因测试用例[0,0,0]而失败。我相信目标被计算为零,但是二分查找选择了i + 1中的零,因此解决方案被拒绝了。有人对如何解决此问题有任何建议吗?
答案 0 :(得分:0)
好吧,如果您想使用二进制搜索进行操作,就可以了。我已经修复了一些逻辑错误,进行了一些改进,并添加了一些注释,希望对您有所帮助。该代码已被leetcode接受,但不是那么有效的解决方案。时间复杂度为O(n ^ 2 * logn)。使用2 pointers approach可以在O(n ^ 2)中完成。
public int binary_search(int[] nums, int start, int end, int target) {
if (start > end) {
return -1;
}
int mid = (start + end) / 2;
if (nums[mid] == target) {
return mid;
} else {
if (nums[mid] < target) {
return binary_search(nums, mid + 1, end, target);
} else {
return binary_search(nums, start, mid - 1, target);
}
}
}
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
ArrayList<List<Integer>> solution_set = new ArrayList<>();
// you can't do it using only one loop.
// Take a look at this sample input -2,0,1,1,2.
// Here you have to consider for nums[i] and nums[j] -2, 0 as well as
// -2, 1
for (int i = 0; i < nums.length - 2; i++) {
// skip duplicates
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1; j < nums.length - 1; j++) {
int number_1 = nums[i];
int number_2 = nums[j];
// skip duplicates and, since array is sorted, don't need to
// consider values > 0
if (i != j - 1 && nums[j - 1] == nums[j] || number_1 + number_2 > 0)
continue;
int target = -(number_1 + number_2);
// since array is sorted, start binary search only from j + 1
int target_index = binary_search(nums, j + 1, nums.length - 1, target);
if (target_index != -1) {
List<Integer> submission = new ArrayList<>();
submission.add(number_1);
submission.add(number_2);
submission.add(target);
solution_set.add(submission);
}
}
}
return solution_set;
}
输出:
[[0, 0, 0]]
[[-2, 0, 2], [-2, 1, 1]]
[[-1, -1, 2], [-1, 0, 1]]