按照一个数的大小分裂数组,以及荷兰国旗问题

给定一个数组arr, 和一个数num, 请把小于等于num的数放在数组的左边, 大于num的数放在数组的右边。

要求额外空间复杂度O(1), 时间复杂度O(N)。

Python代码

def split_array(arr, num):
    """维持一个小于等于区域的index,
    如果一个数小于等于num,则和index位置交换
    如果一个数大于num,则直接跳下一个
    """
    i = 0
    for j in range(len(arr)):
        if arr[j] > num:
            pass
        else:
            arr[j], arr[i] = arr[i], arr[j]
            i += 1
    return arr

问题二(荷兰国旗问题)
给定一个数组arr, 和一个数num, 请把小于num的数放在数组的左边, 等于num的数放在数组的中间, 大于num的数放在数组的右边。

要求额外空间复杂度O(1), 时间复杂度O(N)

def split_array(arr, num):
    """总体的策略是,遇到小的数字,那么把它往前面移动,遇到大的数字,把它让后面移动,遇到相等的数字,不动
    维持两个三个变量来进行交换 less  , more , current
    其中more的值应该为len(arr),这样在判断的时候多判断一次,并且j-=1写在后面

    more要等于len(arr),并且运算的时候先要减一,否则会出现这种情况:
    [7,6,4,1,2,5,4] 变为[2, 4, 4, 1, 5, 6, 7],因为这种情况下面并没有对中间的1进行排序,少了一次排序的次数
    """
    current = 0
    less = 0
    more = len(arr)
    while(current < more):
        if arr[current] < num:      # 如果小于,那么less和current要进行交换,并且都推进一位
            arr[less], arr[current] = arr[current], arr[less]
            less += 1
            current += 1
        elif arr[current] == num:   # 如果等于,那么直接向下进行
            current += 1
        else:
            more -= 1
            arr[current], arr[more] = arr[more], arr[current]
    return arr


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答这个问题。首先,层次聚类是一种聚类方法,它将数据点逐渐合并成越来越大的群集。在这种方法中,我们不需要提前指定要聚类的群集数量,因为层次聚类会自动确定最终的聚类结果。 下面是使用C++实现层次聚类的基本步骤: 1. 定义一个二维数组来存储数据点之间的距离 ```c++ double dist[N][N]; ``` 其中`N`是数据点的数量。 2. 初始化距离矩阵 在层次聚类的开始时,每个数据点都是一个单独的群集。因此,我们将距离矩阵初始化为每个数据点与其他数据点之间的欧几里得距离。 ```c++ for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (i == j) { dist[i][j] = 0.0; } else { double d = 0.0; for (int k = 0; k < D; k++) { d += (data[i][k] - data[j][k]) * (data[i][k] - data[j][k]); } dist[i][j] = sqrt(d); } } } ``` 其中`data`是存储数据的数组,`D`是每个数据点的维数。 3. 执行层次聚类 层次聚类有两种方法:凝聚(自下而上)和分裂(自上而下)。这里我们使用凝聚方法。 在凝聚方法中,我们从最小的群集开始,逐渐合并成越来越大的群集。具体来说,我们从所有单独的数据点开始,将距离最近的两个点合并成一个群集,然后更新距离矩阵,继续合并距离最近的两个群集,直到所有数据点都在同一个群集中。 ```c++ int cluster[N]; for (int i = 0; i < N; i++) { cluster[i] = i; } while (true) { // 找到距离最近的两个群集 int c1, c2; double min_dist = INF; for (int i = 0; i < N; i++) { for (int j = 0; j < i; j++) { if (dist[i][j] < min_dist && cluster[i] != cluster[j]) { min_dist = dist[i][j]; c1 = i; c2 = j; } } } // 如果所有数据点都在同一个群集中,则结束聚类 if (min_dist == INF) { break; } // 合并两个群集并更新距离矩阵 for (int i = 0; i < N; i++) { if (cluster[i] == cluster[c2]) { cluster[i] = cluster[c1]; } dist[c1][i] = dist[i][c1] = min(dist[c1][i], dist[c2][i]); } } ``` 在上面的代码中,我们使用数组`cluster`来记录每个数据点所属的群集。初始时,每个数据点都是一个单独的群集。当两个群集合并时,我们将其中一个群集的所有数据点的`cluster`值更新为另一个群集的`cluster`值。 在更新距离矩阵时,我们使用单链接(single linkage)方法。也就是说,两个群集之间的距离等于它们之间距离最近的两个数据点之间的距离。 4. 输出聚类结果 聚类结束后,我们可以将数据点按照所属的群集进行分类,并输出聚类结果。 ```c++ for (int i = 0; i < N; i++) { cout << "Data point " << i << " belongs to cluster " << cluster[i] << endl; } ``` 完整的代码实现如下:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值