学习算法第一课(二分法)

 学习算法,不许喷哦,学习奋斗中,程序猿之积木堆积者

需求:在B2C中,B端为了考核C端,出现需要根据阶梯达标量来判断该C端是否符合标准,符合标准则根据标准情况奖励产品

例如:小明是供货商、小爱和小霞是经销商,小明需要根据销售数量来判断小爱是不是每天都达标。

小明制定得标准是:

        1、合同量小于1吨得时候,每天的总库存量不能低于10件、每天线上库存量不能低于4件,每天的销售量不能低于2件

        2、合同量大于1吨且小于4吨得时候,每天的总库存量不能低于50件、每天线上库存量不能低于20件,每天的销售量不能低于12件

        ....依次类推

        100、合同量大于100吨的时候,每天的总库存量不能低于500件、每天线上库存量不能低于300件,每天的销售量不能低于130件

小爱的合同量为:3吨

小霞的合同量为:40吨

如此会得出结论:

合同量范围总库存线上库存销售量
0~110 42
1~4502012
100~无穷大500300130

为了尽快定位根据合同量下的数据,因此采用以下算法实现

直接上代码

1、引入jar包如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.core</groupId>
	<artifactId>test</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>test</name>
	<description>test</description>

	<properties>
		<java.version>1.8</java.version>
		<fastjson2.version>2.0.11</fastjson2.version>
	</properties>

	<dependencies>
		<!-- springboot基础应用包 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-tomcat</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- 启动容器undertow -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-undertow</artifactId>
		</dependency>
		<!-- 阿里数据json处理 -->
		<dependency>
			<groupId>com.alibaba.fastjson2</groupId>
			<artifactId>fastjson2</artifactId>
			<version>${fastjson2.version}</version>
		</dependency>
		<!-- 单元测试 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

2、代码如下:

import com.alibaba.fastjson2.JSON;
import lombok.SneakyThrows;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 算法理解一课
 * 深度理解冒泡和二分法
 * @Author: java-cj
 * */
@SpringBootTest
@Slf4j
public class TestApi {

    /**
     * 需求说明
     * 根据数据库存储和同量判断当前总库存量是否合格,不合格进行预警或者报警
     * 1、合同量是数据库存储的(每年都会有变动,变动意味着营销会变动)
     * 2、合同量的区间和区间值是根据客户提供标准(每年都会有调整,因此采用存储可变模式===系统字典存储)
     * */
    @Test
    public void test() {
        // 1865
        Map<String, Object> map = new HashMap<>();
        // 总库存量
        map.put("allQty", "{\"region\":\"0\",\"result\":\"1\",\"isAdoptedContract\":\"false\",\"color\":\"#153153\",\"bgColor\":\"#ffffff\",\"defaultColor\":\"#000000\",\"defaultBgColor\":\"#ffffff\"}");
        // 线上库存量
        //map.put("onlineQty", "{\"region\":\"0,10\",\"result\":\"12,20\","isAdoptedContract":"false",\"color\":\"#153153\",\"bgColor\":\"#ffffff\","defaultColor":"#000000","defaultBgColor":"#ffffff"}");
        // 销售量
        //map.put("salesQty", "{\"region\":\"0,5,10,15,20\",\"result\":\"2,4,6,8,10\","isAdoptedContract":"false",\"color\":\"#153153\",\"bgColor\":\"#ffffff\","defaultColor":"#000000","defaultBgColor":"#ffffff"}");

        JSONObject jsonObject = changeObject("allQty", 0, 10, map);
        System.out.println(jsonObject);
    }

    /**
     * 根据数据进行尽快定位数据所在区间
     *
     * @param key         传入的key(数据库查询出来得字段)
     * @param value       传入的value(数据库查询出来得值,目前得总库存量)
     * @param contractNum 传入的合同量(数据库中根据数据分析出来得合同量)
     */
    @SneakyThrows
    public JSONObject changeObject(String key, int value, int contractNum, Map<String, Object> map) {
        // 获取字典得值  不行就用map循环
        JSONObject object = JSON.parseObject(new JSONObject(map).getString(key));
        // 获取结果(数据必须时有序,且必须是一个区间包含一个值)
        // 区间结果
        String region = object.getString("region");
        // 区间对应值结果
        String result = object.getString("result");
        // 渲染数据颜色
        String color = object.getString("color");
        // 渲染数据背景颜色
        String bgColor = object.getString("bgColor");
        // 默认字体颜色
        String defaultColor = object.getString("defaultColor");
        // 背景颜色
        String defaultBgColor = object.getString("defaultBgColor");
        // 是否采用合同
        boolean isAdoptedContract = object.getBoolean("isAdoptedContract");

        JSONObject jsonObject = new JSONObject();
        if (contractNum == 0) {
            if (value > 0) {
                jsonObject.put("value", value);
                jsonObject.put("color", defaultColor);
                jsonObject.put("bgColor", defaultBgColor);
            } else {
                jsonObject.put("value", value);
                jsonObject.put("color", color);
                jsonObject.put("bgColor", bgColor);
            }
        } else {
            // 冒泡法
            // int resNum = bubbling(region, result, isAdoptedContract?contractNum:0);
            // 二分法
            int resNum = dichotomy(region, result, isAdoptedContract?contractNum:0);
            if (resNum <= value) {
                jsonObject.put("value", value);
                jsonObject.put("color", defaultColor);
                jsonObject.put("bgColor", defaultBgColor);
            } else {
                jsonObject.put("value", value);
                jsonObject.put("color", color);
                jsonObject.put("bgColor", bgColor);
            }
        }
        return jsonObject;
    }

    /**
     * 冒泡获取结果 (效率不高  很慢  完全可以实现)
     * @param regin 取值区间
     * @param result 区间对应结果
     * @param contract 当前拥有合同量
     */
    public int bubbling(String regin, String result, int contract) {
        List<String> regins = Arrays.asList(regin.split(","));
        List<Integer> reginList = regins.stream().map(Integer::parseInt).collect(Collectors.toList());
        // 结果
        List<String> results = Arrays.asList(result.split(","));
        List<Integer> resultList = results.stream().map(Integer::parseInt).collect(Collectors.toList());
        // 若入参比数组中最大数还大,则取值最大区间
        if (contract >= reginList.get(resultList.size() - 1)) {
            return resultList.get(resultList.size() - 1);
        }
        int iNum = -1;
        for (int i = 0; i < reginList.size(); i++) {
            if (reginList.get(i) >= contract) {
                iNum = i;
                break;
            }
        }
        return resultList.get(iNum - 1);
    }

    /**
     * 二分法获取结果
     * @param regin 取值区间
     * @param result 区间对应结果
     * @param contract 当前拥有合同量
     */
    public int dichotomy(String regin, String result, int contract) {
        // 获取区域
        List<String> regins = Arrays.asList(regin.split(","));
        List<Integer> reginList = regins.stream().map(Integer::parseInt).collect(Collectors.toList());
        // 返回区域结果
        List<String> results = Arrays.asList(result.split(","));
        List<Integer> resultList = results.stream().map(Integer::parseInt).collect(Collectors.toList());
        // 若入参比数组中最大数还大,则取值最大区间
        if (contract > reginList.get(resultList.size() - 1)) {
            return resultList.get(resultList.size() - 1);
        }
        // 进行二分
        int left = 0;
        int right = reginList.size() - 1;
        int mid = (left + right) / 2;
        int index = -1;
        // 查找
        while (left <= right) {
            if (reginList.get(mid) == contract) {
                index = mid;
                break;
            } else if (reginList.get(mid) < contract) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
            mid = (right + left) / 2;
        }
        if (index == mid) {
            return resultList.get(index);
        } else {
            return resultList.get(mid);
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值