477. Total Hamming Distance

本文介绍了一种计算一组整数中所有不同整数对之间的汉明距离总和的方法。通过位运算来统计每一对整数在相同位置上不同比特的数量,并提供了具体的实现代码。

The Hamming distance between two integers is the number of positions at which the corresponding bits are different.

Now your job is to find the total Hamming distance between all pairs of the given numbers.

Example:

Input: 4, 14, 2

Output: 6

Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just
showing the four bits relevant in this case). So the answer will be:
HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.

Note:

  1. Elements of the given array are in the range of to 10^9
  2. Length of the array will not exceed 10^4.

int totalHammingDistance(vector<int>& nums) {
      int i,j,n=nums.size();
      if(!n) return 0;
      int sum=0;
      while(maxnum(nums))
      {
          int c0=0,c1=0;
          for(i=0;i<n;i++)
          {
              if(nums[i]&1)
              c1++;
              else c0++;
              nums[i]>>=1;
          }
          sum+=c1*c0;
      }
      return sum;
    }
    int maxnum(vector<int>nums)
    {
        int r=nums[0];
        for(auto i:nums)
        r=max(r,i);
        return r;
    }

f = { 0: { '0': 2, '1': 1 }, 1: { '00': 2, '01': 3, '10': 2, '11': 0 }, 2: { '000': 0, '001': 1, '010': 1, '011': 0, '100': 2, '101': 0, '110': 0, '111': 0 } } import random def generate_sequence(N): # TODO ''' generates an N random bits (0, 1) sequence Parameters: ----------- N : number of bits in the sequence Returns: -------- sequence: sequence of N bits ''' sequence=[] for i in range(N) : sequence.append(random.choice(['0', '1'])) # generate a random sequence of N bits (0, 1) return sequence def compute_fitness(sequence, K): # TODO ''' computes the fitness of sequence, with respect to K, according to table f Parameters: ----------- sequence : N-bits sequence K : parameter K (0, 1, or 2) Returns: -------- fitness: fitness value of sequence ''' seq = str(sequence) N = len(seq) fitness = 0 if K == 0: # f0: 0->2, 1->1 for bit in seq: fitness += 2 if bit == '0' else 1 elif K == 1: # f1: 00->2, 01->3, 10->2, 11->0 for i in range(N): pair = seq[i] + seq[(i+1) % N] if pair == '00': fitness += 2 elif pair == '01': fitness += 3 elif pair == '10': fitness += 2 elif K == 2: # f2: 000->0 001->1 010->1 011->0 100->2 101->0 110->0 111->0 for i in range(N): triple = seq[i] + seq[(i+1) % N] + seq[(i+2) % N] if triple == '001' or triple == '010': fitness += 1 elif triple == '100': fitness += 2 return fitness def neighbors(sequence): ''' returns all neighbors of sequence () Parameters: ----------- sequence : N-bits sequence Returns: -------- generator of neighbors of sequence ''' for i in range(len(sequence)): if sequence[i] == '0': new = '1' else: new = '0' yield (sequence[:i] + new + sequence[i + 1:]) # generate all neighbors that differ in 1 bit def mean_steps(samples): ''' returns mean of steps taken to find solution (for deterministic) Parameters: ----------- samples : samples of deterministic_hillclimb runs Returns: -------- mean steps ''' # get mean of steps needed to find solution (sum of samples' steps/number of samples) return sum(x[2] for x in samples)/len(samples) def generate_samples(hillclimb_method, K): ''' generates 50 samples (solutions) for the hillclimb method (deterministic/probabilistic) Parameters: ----------- hillclimb_method : deterministic_hillclimb/probabilistic_hillclimb K : parameter K (0, 1, or 2) Returns: -------- generator of samples/solutions (sequence, fitness, number of steps) ''' if K not in [0, 1, 2]: raise Exception("Invalid K") # run for 50 times to get 50 samples/solutions for i in range(50): # generate initial sequence initial_sequence = generate_sequence(N=21) # get solution, its fitness, number of steps taken to find solution x, f_x, s = hillclimb_method(initial_sequence, K) yield (x, f_x, s) def deterministic_hillclimb(sequence, K): # TODO ''' performs deterministic_hillclimb Parameters: ----------- sequence : N-bits sequence K : parameter K (0, 1, or 2) Returns: -------- sequence : optimal/fittest sequence found max_fitness : fitness value of sequence steps: steps it took to reach optimum ''' current_solution = sequence current_value = compute_fitness(current_solution, K) steps = 0 # 记录每次迭代的最佳值 best_values = [current_value] # 迭代寻找更好的解 for i in range(50): # 最多迭代50次 # 生成邻近解 neighbor = neighbors(current_solution,K) neighbor_value = compute_fitness(neighbor, K) # 如果邻近解更优,则更新当前解 if neighbor_value < current_value: current_solution = neighbor current_value = neighbor_value else: pass # 没有改进,保持当前解不变 best_values.append(current_value) # 记录当前最佳值 return current_solution, current_value, best_values # dictionary to save deterministic_hillclimb samples (sequence, max_fitness, steps) deterministic_samples = {} # dictionary to save number of steps to perform probabilistic hillclimb probabilistic_steps = {} # run deterministic_hillclimb, get mean steps for K in [0, 1, 2]: # for each K, generate 50 deterministic_hillclimb solutions, and save them deterministic_samples[K] = list(generate_samples(deterministic_hillclimb, K)) # for each K, save the number of steps to take (10*mean steps taken for deterministic_hillclimb) probabilistic_steps[K] = 10*round(mean_steps(deterministic_samples[K])) def probabilistic_hillclimb(sequence, K): # TODO ''' performs probabilistic_hillclimb Parameters: ----------- sequence : N-bits sequence K : parameter K (0, 1, or 2) Returns: -------- sequence : optimal/fittest sequence found max_fitness : fitness value of sequence steps: steps corresponding to parameter K ''' current_solution = sequence current_value = compute_fitness(current_solution, K) steps = 0 max_iterations = probabilistic_steps[K] import numpy as np for _ in range(max_iterations): # Generate all neighbors neighbor_list = [] for i in range(len(current_solution)): neighbor = list(current_solution) neighbor[i] = '1' if neighbor[i] == '0' else '0' neighbor_list.append(''.join(neighbor)) neighbor_values = [compute_fitness(neighbor, K) for neighbor in neighbor_list] # Calculate selection probabilities (higher fitness gets higher probability) total = sum(neighbor_values) if total == 0: probabilities = [1/len(neighbor_values)] * len(neighbor_values) else: probabilities = [v/total for v in neighbor_values] # Randomly select a neighbor based on probabilities selected_index = np.random.choice(len(neighbor_list), p=probabilities) selected_neighbor = neighbor_list[selected_index] selected_value = neighbor_values[selected_index] # Update current solution if better if selected_value > current_value: current_solution = selected_neighbor current_value = selected_value steps += 1 return current_solution, current_value, steps # dictionary to save probabilistic_hillclimb samples (sequence, max_fitness, steps) probabilistic_samples = {} # run probabilistic_hillclimb for K in [0, 1, 2]: # for each K, generate 50 probabilistic_hillclimb solutions, and save them probabilistic_samples[K] = list(generate_samples(probabilistic_hillclimb, K)) def hamming_distance(sequence1, sequence2): # TODO ''' returns hamming distance between sequence1 and sequence2 Parameters: ----------- sequence1 : N-bits sequence sequence2 : N-bits sequence Returns: -------- distance : hamming distance between sequence1 and sequence2 ''' xor_result = sequence1 ^ sequence2 return bin(xor_result).count('1') import matplotlib.pyplot as plt # 分析并绘制汉明距离 def analyze_and_plot_hamming(N=21, num_runs=50): # 存储结果 hamming_results = {} for K in [0, 1, 2]: print(f"处理 K={K}") hamming_results[K] = {'deterministic': [], 'probabilistic': []} # 存储解 det_solutions = [] prob_solutions = [] # 运行实验 for run in range(num_runs): seq = generate_sequence(N) # 确定性爬山 det_sol, _, _ = deterministic_hillclimb(seq, K) det_solutions.append(det_sol) # 概率性爬山 prob_sol, _, _ = probabilistic_hillclimb(seq, K) prob_solutions.append(prob_sol) # 计算汉明距离 hamming_results[K]['deterministic'] = get_all_hamming_distances(det_solutions) hamming_results[K]['probabilistic'] = get_all_hamming_distances(prob_solutions) # 绘制结果 plot_hamming_results(hamming_results) return hamming_results # 计算所有解对之间的汉明距离 def get_all_hamming_distances(solutions): distances = [] n = len(solutions) for i in range(n): for j in range(i+1, n): dist = hamming_distance(solutions[i], solutions[j]) distances.append(dist) return distances 这是我的全部的代码,请编写 Plot and analyze pairwise hamming distances for all methods and K values的答案代码
最新发布
09-24
以下是一个Python示例代码,用于模拟确定性爬山和概率性爬山方法,并绘制在K值为0、1、2时的成对汉明距离。这里假设我们有一个简单的二进制解空间来进行爬山搜索。 ```python import numpy as np import matplotlib.pyplot as plt from scipy.spatial.distance import hamming # 定义目标函数,这里简单用二进制解的1的数量作为适应度 def fitness(solution): return np.sum(solution) # 生成随机初始解 def generate_initial_solution(length): return np.random.randint(0, 2, length) # 生成邻居解 def get_neighbors(solution, k): neighbors = [] indices = np.arange(len(solution)) np.random.shuffle(indices) for i in range(k + 1): neighbor = solution.copy() neighbor[indices[:i + 1]] = 1 - neighbor[indices[:i + 1]] neighbors.append(neighbor) return neighbors # 确定性爬山法 def deterministic_hill_climbing(initial_solution, k): current_solution = initial_solution current_fitness = fitness(current_solution) while True: neighbors = get_neighbors(current_solution, k) best_neighbor = None best_fitness = -1 for neighbor in neighbors: neighbor_fitness = fitness(neighbor) if neighbor_fitness > best_fitness: best_fitness = neighbor_fitness best_neighbor = neighbor if best_fitness <= current_fitness: break current_solution = best_neighbor current_fitness = best_fitness return current_solution # 概率性爬山法 def probabilistic_hill_climbing(initial_solution, k, probability=0.5): current_solution = initial_solution current_fitness = fitness(current_solution) while True: neighbors = get_neighbors(current_solution, k) best_neighbor = None best_fitness = -1 for neighbor in neighbors: neighbor_fitness = fitness(neighbor) if neighbor_fitness > best_fitness: best_fitness = neighbor_fitness best_neighbor = neighbor if np.random.rand() < probability and best_fitness > current_fitness: current_solution = best_neighbor current_fitness = best_fitness else: break return current_solution # 计算成对汉明距离 def pairwise_hamming_distances(solutions): n = len(solutions) distances = [] for i in range(n): for j in range(i + 1, n): distances.append(hamming(solutions[i], solutions[j]) * len(solutions[i])) return distances # 实验参数 solution_length = 20 num_runs = 100 k_values = [0, 1, 2] # 存储结果 deterministic_distances = {k: [] for k in k_values} probabilistic_distances = {k: [] for k in k_values} # 运行实验 for k in k_values: deterministic_solutions = [] probabilistic_solutions = [] for _ in range(num_runs): initial_solution = generate_initial_solution(solution_length) deterministic_solution = deterministic_hill_climbing(initial_solution, k) probabilistic_solution = probabilistic_hill_climbing(initial_solution, k) deterministic_solutions.append(deterministic_solution) probabilistic_solutions.append(probabilistic_solution) deterministic_distances[k] = pairwise_hamming_distances(deterministic_solutions) probabilistic_distances[k] = pairwise_hamming_distances(probabilistic_solutions) # 绘制箱线图 fig, axes = plt.subplots(1, 2, figsize=(12, 6)) # 确定性爬山法 axes[0].boxplot([deterministic_distances[k] for k in k_values], labels=k_values) axes[0].set_title('Deterministic Hill Climbing') axes[0].set_xlabel('k value') axes[0].set_ylabel('Pairwise Hamming Distance') # 概率性爬山法 axes[1].boxplot([probabilistic_distances[k] for k in k_values], labels=k_values) axes[1].set_title('Probabilistic Hill Climbing') axes[1].set_xlabel('k value') axes[1].set_ylabel('Pairwise Hamming Distance') plt.tight_layout() plt.show() ``` ### 代码解释 1. **目标函数**:`fitness` 函数用于计算二进制解的适应度,即解中 1 的数量。 2. **初始解生成**:`generate_initial_solution` 函数生成一个随机的二进制解。 3. **邻居解生成**:`get_neighbors` 函数根据当前解生成邻居解,通过翻转最多 `k + 1` 位。 4. **确定性爬山法**:`deterministic_hill_climbing` 函数实现了确定性爬山算法,总是选择最优的邻居解。 5. **概率性爬山法**:`probabilistic_hill_climbing` 函数实现了概率性爬山算法,以一定的概率选择最优邻居解。 6. **成对汉明距离计算**:`pairwise_hamming_distances` 函数计算一组解之间的成对汉明距离。 7. **实验运行**:通过多次运行实验,记录不同 `k` 值下确定性和概率性爬山法的最终解,并计算成对汉明距离。 8. **绘制箱线图**:使用 `matplotlib` 绘制箱线图,展示不同 `k` 值下的成对汉明距离分布。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值