非暴力法求解Two Sum问题:Python代码错误排查求助
Hey there! Let's break down what's messing up your implementation and work through solid fixes step by step.
Why the remove command breaks your code
When you call l.remove(new) inside your for i in range(len(l)) loop, you're directly modifying the list you're actively iterating over—this creates two critical issues:
- Dynamic list length mismatch: The
range(len(l))generates a sequence based on the list's initial length. But once you remove elements, the list gets shorter, so later values ofiwill either point to nonexistent indices or skip over elements entirely. For example, if your list starts as[2,7,11,15]and you remove 7 after the first iteration, the list becomes[2,11,15]. Wheni=1rolls around, you'll accessl[1](which is 11 now), but the original element at index 1 is already gone—your loop logic is completely thrown off. index()only finds the first match: If your list has duplicate values (like[3,3]),l.index(new)will always return the first occurrence's index. When you remove that element, the remaining duplicate will still try to reference the now-missing index, leading to wrong results or errors.
Why skipping remove causes duplicate results
Without remove, your code checks every element against the entire list every time. For example, with [2,7,11,15] and target 9:
- When
i=0, you find 7 (index 1) and add(0,1)to the result. - When
i=1, you calculate9-7=2, which is still in the list, so you add(1,0)to the result.
This gives you duplicate pairs because you're counting each valid pair twice (once from each element's perspective).
Correct Implementations (Two Common Approaches)
Approach 1: Hash Map (Optimal, O(n) Time Complexity)
Use a dictionary to track elements and their indices as you iterate. This lets you check for the required complement in constant time, avoids duplicates, and never modifies the original list.
def two_sum(l, sval): num_to_index = {} result = [] for idx, num in enumerate(l): complement = sval - num if complement in num_to_index: result.append((num_to_index[complement], idx)) # Store the current number and index (overwrites duplicates, which works for most cases) num_to_index[num] = idx return result
Test cases:
two_sum([2,7,11,15], 9)returns[(0,1)](correct)two_sum([3,3], 6)returns[(0,1)](correct)two_sum([2,5,5,11], 10)returns[(1,2)](correct)
Approach 2: Double Loop (No Hash Map, O(n²) Time Complexity)
If you prefer a simpler (though less efficient) approach, use nested loops where the inner loop starts at i+1. This ensures each pair is only checked once, so no duplicates.
def two_sum(l, sval): result = [] for i in range(len(l)): # Start j after i to avoid checking the same pair twice for j in range(i + 1, len(l)): if l[i] + l[j] == sval: result.append((i, j)) return result
Adjusting Your Original Logic (If You Want to Keep It)
If you want to stick with your initial idea of checking for the complement, just avoid modifying the original list and track processed indices to skip duplicates:
def two_sum(l, sval): result = [] processed_indices = set() for i in range(len(l)): if i in processed_indices: continue complement = sval - l[i] if complement in l: j = l.index(complement) # Make sure we're not pairing an element with itself, and j isn't processed if j != i and j not in processed_indices: result.append((i, j)) processed_indices.add(i) processed_indices.add(j) return result
内容的提问来源于stack exchange,提问作者Herodus

