最优商品topk排名算法

简介: 最优商品topk排名算法

1 产生背景

topk是一个典型的业务场景,除了最优商品,包括推荐排名、积分排名所有涉及到排名前k的地方都是该算法的应用场合。

topk即得到一个集合后,筛选里面排名前k个数值。问题看似简单,但是里面的数据结构和算法体现着对解决方案性能的思索和深度挖掘。到底有几种方法,这些方案里蕴含的优化思路究竟是怎么样的?这节来讨论


2 解决方案

2.1 方案一:全局排序

全局排序,将集合整体排序后,取出最大的k个值就是需要的结果。

这种方案最糟糕,我只需要排名前k的元素,其他n-k个的顺序我并不关心,但是运算过程中,都得跟着做了没用的排序操作。


2.2 方案二:局部排序

局部排序,既然全局没必要,那我只取前k个,后面的就没必要理会了。

冒泡排序在排序算法中可以胜任该操作。我们按最大值往上冒泡为例,只要执行k次冒泡,那前k名就可以确定。但是这种方案依然不是最优办法。因为我们需要的是前k名,那至于这k个,谁大谁小并不需要关心,排序依然是个浪费。


2.3 方案三:最小堆

最小堆,既然没必要排序,那我们就不排序。

先将前k个元素形成一个最小堆,后面的n-k个元素依次与堆顶比较,小则丢弃大则替换堆顶并调整堆。直到n个全部完成为止。最小堆是topk的经典解决方案。


3 实现

下面就用最小堆实现topk

package com.oldlu.busi;
import java.util.Arrays;
public class Topk {
    //堆元素下沉,形成最小堆,序号从i开始
    static void down(int[] nodes,int i) {
        //顶点序号遍历,只要到1半即可,时间复杂度为O(log2n)
        while ( i << 1  <  nodes.length){
            //左子,为何左移1位?回顾一下二叉树序号
            int left = i<<1;
            //右子,左+1即可
            int right = left+1;
            //标记,指向 本节点,左、右子节点里最小的,一开始取i自己
            int flag = i;
            //判断左子是否小于本节点
            if (nodes[left] < nodes[i]){
                flag = left;
            }
            //判断右子
            if (right < nodes.length && nodes[flag] > nodes[right]){
                flag = right;
            }
            //两者中最小的与本节点不相等,则交换
            if (flag != i){
                int temp = nodes[i];
                nodes[i] = nodes[flag];
                nodes[flag] = temp;
                i = flag;
            }else {
                //否则相等,堆排序完成,退出循环即可
                break;
            }
        }
    }
    public static void main(String[] args) {
        //原始数据
        int[] src={3,6,2,7,4,8,1,9,2,5};
        //要取几个
        int k = 5;
        //堆,为啥是k+1?请注意,最小堆的0是无用的,序号从1开始
        int[] nodes = new int[k+1];
        //取前k个数,注意这里只是个二叉树,还不满足最小堆的要求
        for (int i = 0; i < k; i++) {
            nodes[i+1]=src[i];
        }
        System.out.println("before:"+Arrays.toString(nodes));
        //从最底的子树开始,堆顶下沉
        //这里才真正的形成最小堆
        for (int i = k>>1; i >= 1; i‐‐) {
down(nodes,i);
        }
        System.out.println("create:"+Arrays.toString(nodes));
        //把余下的n‐k个数,放到堆顶,依次下沉,topk堆算法的开始
        for (int i = src.length ‐ k;i<src.length;i++){
            if (nodes[1] < src[i]){
                nodes[1] = src[i];
                down(nodes,1);
            }
        }
        System.out.println("topk:"+Arrays.toString(nodes));
    }
}

4 结果分析

最终获取k个值成功,符合要求

中间不涉及排序问题


目录
相关文章
|
9月前
|
机器学习/深度学习 自然语言处理 算法
小红书:通过商品标签API自动生成内容标签,优化社区推荐算法
小红书通过商品标签API自动生成内容标签,提升推荐系统精准度与用户体验。流程包括API集成、标签生成算法与推荐优化,实现高效率、智能化内容匹配,助力社交电商发展。
|
8月前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
9月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。
|
搜索推荐 算法 前端开发
商品购物管理与推荐系统Python+Django网页界面+协同过滤推荐算法
商品购物管理与推荐系统Python+Django网页界面+协同过滤推荐算法
496 0
|
SQL 算法 Serverless
B端算法实践问题之使用concat_id算子获取用户最近点击的50个商品ID如何解决
B端算法实践问题之使用concat_id算子获取用户最近点击的50个商品ID如何解决
249 1
|
数据采集 机器学习/深度学习 算法
Python基于Apriori关联规则算法实现商品零售购物篮分析
Python基于Apriori关联规则算法实现商品零售购物篮分析
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
|
存储 机器学习/深度学习 算法
数据结构与算法⑬(第四章_中_续二)堆解决Topk问题+堆的概念选择题
数据结构与算法⑬(第四章_中_续二)堆解决Topk问题+堆的概念选择题
299 3
|
算法
【优选算法】——Leetcode——LCR 179. 查找总价格为目标值的两个商品
【优选算法】——Leetcode——LCR 179. 查找总价格为目标值的两个商品
250 2
|
搜索推荐 算法
基于用户的协同过滤算法实现商品推荐
基于用户的协同过滤算法实现商品推荐
517 2

热门文章

最新文章