Hot100——普通数组

53最大子数字

思路

  1. 核心思想

    • 遍历数组时,持续维护一个当前子数组的和(now
    • 同时记录遍历过程中遇到的最大子数组和(ans
  2. 具体逻辑

    • 初始化 now 为 0(当前子数组和),ans 为一个极小值(-1e9,确保能覆盖所有可能的负值情况)
    • 遍历数组中的每个元素:
      • 将当前元素加入 now(扩展当前子数组)
      • 用 now 更新 ans(保留最大值)
      • 如果 now 小于 0,说明当前子数组的和为负,继续保留会拖累后续结果,因此重置 now 为 0(相当于重新开始一个新的子数组)
  3. 适用场景

    • 解决 "最大子序和" 问题,即从整数数组中找出一个具有最大和的连续子数组
    • 能高效处理包含负数的数组,例如 [-2,1,-3,4,-1,2,1,-5,4] 这样的输入,会正确返回 6(对应子数组 [4,-1,2,1]

这个算法的优势在于只需要一次遍历就能得到结果,是解决此类问题的最优方案之一。

代码

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end(),[](const vector<int> &a,const vector<int> &b)
        {
            if(a[0]!=b[0])
            {
                return a[0]<b[0];
            }
            return a[1]<b[1];
        });

        vector<vector<int>> ans;

        int st=intervals[0][0],end=intervals[0][1];
        for(int i=1;i<intervals.size();i++)
        {
            if(intervals[i][0]<=end)
            {
                end=max(end,intervals[i][1]);
            }
            else 
            {
                ans.push_back({st,end});
                st=intervals[i][0];
                end=intervals[i][1];
            }
        }
        ans.push_back({st,end});
        return ans;

    }
};

56合并区间

思路

  1. 区间排序

    • 首先对所有区间进行排序,排序规则是先按区间的起始位置(a[0])升序排列
    • 若起始位置相同,则按区间的结束位置(a[1])升序排列
    • 排序的目的是让后续的合并过程可以按顺序进行,确保相邻的区间在物理位置上也相邻
  2. 区间合并逻辑

    • 初始化stend为第一个区间的起始和结束位置
    • 从第二个区间开始遍历:
      • 若当前区间的起始位置intervals[i][0]小于等于end,说明两个区间重叠或相邻,将end更新为两个区间结束位置的最大值(合并区间)
      • 若当前区间的起始位置大于end,说明两个区间不重叠,将之前合并好的区间[st, end]加入结果集,然后更新stend为当前区间的起始和结束位置
    • 遍历结束后,将最后一个合并的区间加入结果集
  3. 示例说明

    • 对于输入[[1,3],[2,6],[8,10],[15,18]],排序后不变
    • 合并过程:[1,3][2,6]合并为[1,6],然后[8,10][15,18]保持不变
    • 最终结果为[[1,6],[8,10],[15,18]]

该算法的时间复杂度主要由排序步骤决定,为O(n log n),空间复杂度为O(1)(不考虑存储结果所需的空间),是区间合并问题的经典高效解法。

代码

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end(),[](const vector<int> &a,const vector<int> &b)
        {
            if(a[0]!=b[0])
            {
                return a[0]<b[0];
            }
            return a[1]<b[1];
        });

        vector<vector<int>> ans;

        int st=intervals[0][0],end=intervals[0][1];
        for(int i=1;i<intervals.size();i++)
        {
            if(intervals[i][0]<=end)
            {
                end=max(end,intervals[i][1]);
            }
            else 
            {
                ans.push_back({st,end});
                st=intervals[i][0];
                end=intervals[i][1];
            }
        }
        ans.push_back({st,end});
        return ans;

    }
};

189轮转数组

思路

这段代码实现了数组的向右旋转操作,采用了基于最大公约数(GCD)的环状替换算法,是一种高效的原地旋转方法。具体解析如下:

核心思路

利用数组长度 n 和旋转步数 k 的最大公约数(GCD)来确定旋转的 "环" 数量,每个环内的元素通过环状替换完成旋转,从而实现整体数组的旋转效果。

步骤分解

  1. 特殊情况处理:当 k=0 时,无需旋转,直接返回。

  2. 计算最大公约数

    • 通过自定义的 mygcd 函数计算数组长度 nums.size() 与旋转步数 k 的最大公约数 ma
    • 这个 ma 决定了需要处理的环的数量(即需要进行 ma 次独立的环状替换)。
  3. 环状替换过程

    • 对每个环(从 pos=0 到 pos < ma)进行处理:
      • 保存当前位置 pos 的元素值 last
      • 通过 now = (now + k) % n 计算下一个要替换的位置。
      • 依次将 last 的值放入下一个位置,同时更新 last 为被替换的元素值。
      • 当 now 回到初始位置 pos 时,完成一个环的替换,将最后保存的 last 放入 pos 位置。
    • 递增 pos,处理下一个环,直到所有环都处理完毕。

优势分析

  • 空间效率:原地旋转,仅使用常数级额外空间(O(1))。
  • 时间效率:每个元素仅被移动一次,总时间复杂度为 O(n)
  • 适用性:适用于任意长度的数组和任意旋转步数,包括 k 大于数组长度的情况(通过取模自动处理)。

例如,对于数组 [1,2,3,4,5,6] 和 k=2

  • 数组长度为 6,GCD(6,2)=2,需要处理 2 个环。
  • 第一个环(pos=0):0→2→4→0,元素依次替换。
  • 第二个环(pos=1):1→3→5→1,元素依次替换。
  • 最终结果为 [5,6,1,2,3,4],实现了向右旋转 2 步的效果。

这种算法巧妙利用数学性质减少了操作次数,是数组旋转问题的最优解法之一。

代码

class Solution {
public:

    int mygcd(int a,int b)
    {
        if(a<b)swap(a,b);
        if(b==0)return a;
        return mygcd(b,a%b);
    }

    void rotate(vector<int>& nums, int k) {
        int pos=0;
        if(k==0)return;
        int ma=mygcd(nums.size(),k);
        while (pos < nums.size() && pos < ma)
        {
            int last = nums[pos];
            int tmp;
            int now = pos;
            now += k;
            while (now != pos)
            {
                //cout<<now<<endl;
                now %= nums.size();
                tmp = nums[now];
                nums[now] = last;
                last = tmp;
                now += k;
                now %= nums.size();
            }
            nums[pos] = last;
            pos++;
        }
    }
};

238除自身以外数组的乘积

思路

算法思路解析:

  1. 核心思想

    • 利用两次遍历,分别计算每个元素左侧所有元素的乘积和右侧所有元素的乘积
    • 将这两个乘积相乘,即可得到每个位置除除自身外所有元素的乘积
  2. 具体步骤

    • 第一次遍历(左到右)

      • 初始化 answer[0] = 1(第一个元素左侧没有元素,乘积为 1)
      • 对于 i > 0answer[i] 存储 nums[0] 到 nums[i-1] 的乘积(即当前元素左侧所有元素的乘积)
    • 第二次遍历(右到左)

      • 初始化 R = 1(右侧乘积的初始值)
      • 对于每个 ianswer[i] 乘以 R(即当前元素右侧所有元素的乘积)
      • 更新 R 为 R * nums[i](将当前元素加入右侧乘积,供左侧元素使用)
  3. 优势分析

    • 避免了使用除法(处理了数组中可能包含 0 的情况)
    • 仅使用常数额外空间,效率极高
    • 两次线性遍历,时间复杂度为 O (n)

代码

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int length = nums.size();
        vector<int> answer(length);

        answer[0] = 1;
        for (int i = 1; i < length; i++) {
            answer[i] = nums[i - 1] * answer[i - 1];
        }
        int R = 1;
        for (int i = length - 1; i >= 0; i--) {

            answer[i] = answer[i] * R;

            R *= nums[i];
        }
        return answer;
    }
};

41缺失的第一个正数

思路

代码

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        for(int i=0;i<nums.size();i++)
        {
            while(nums[i]>0&&nums[i]<nums.size())
            {
                swap(nums[i],nums[nums[i]-1]);
                if(nums[i]<=0||nums[i]>=nums.size()||nums[i]==i+1||nums[i]==nums[nums[i]-1])break;
            }
        }

        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]!=i+1)return i+1;
        }

        return nums.size()+1;
    }
};

你的身份是高级编程技术专家,精通各类编程语言,能对编程过程中的各类问题进行分析和解答。我的问题是【我正在编辑【通达信条件选股】代码,遇到了 【RSI6:=RSI(CLOSE,6) 详细信息 : 引用的公式 的第 1 个参数应为数值,而不是数组! 错误起始位置 : 1239 ; 长度: 3】,请帮我检查并改正错误点补全正确代码,生成修正后完整代码。原有选股逻辑完整保留。我的原始代码如下:【{—————————————— 优化后系统参数 ——————————————} {——动态估值体系——} DYNPETTM:=CLOSE/MAX(FINANCE(33)/FINANCE(1),0.000000001); PB_RATE:=CLOSE/MAX(FINANCE(5),0.000000001); PEG_VAL:=DYNPETTM/MAX((FINANCE(54)/MA(FINANCE(34),3))*100,0.000000001); INDUSTRY_RS:=C/REF(C,20)/(INDEXC/REF(INDEXC,20)); {——智能波动率——} VOLATILITY:=STD(CLOSE,20)/MA(CLOSE,20); {统一使用CLOSE替代C} VAR_PERIOD:=FLOOR(60-200*VOLATILITY); FAST_LEN:=CEILING(VAR_PERIOD*0.618); SLOW_LEN:=FLOOR(VAR_PERIOD*1.618); {——情绪引擎——} MARKET_SENTI:=ADVANCE/DECLINE; HOT_INDEX:=EMA(SUM(IF(CLOSE=ZTPRICE(REF(CLOSE,1),0.1),VOL,0),20)/MA(V,20),5); MONEY_FLOW:=EMA((AMOUNT-REF(AMOUNT,1))/REF(AMOUNT,1),3); SENTI_ACCEL:=EMA(MARKET_SENTI,3)*HOT_INDEX/(1+ABS(MONEY_FLOW)); {—————————————— 多周期共振 ——————————————} {——战略层——} MONTH_MA:=EMA(CLOSE,400); MONTH_TREND:=CLOSE>MONTH_MA*1.03 AND SLOPE(MONTH_MA,3)>0; {——战役层——} WEEK_DIF:=EMA(CLOSE,12)-EMA(CLOSE,26); WEEK_DEA:=EMA(WEEK_DIF,9); WEEK_MACD:=2*(WEEK_DIF-WEEK_DEA); WEEK_VOL:=EMA(V,5)>EMA(V,21)*1.3 AND V>REF(MA(V,5),1)*1.6; {——战术层——} DAY_BREAK:=CLOSE>HHV(REF(HHV(HIGH,30),1),3) AND V>MA(V,20)*1.8; RSI6:=RSI(CLOSE,6); {修正参数为CLOSE} RSI12:=RSI(CLOSE,12); RSI24:=RSI(CLOSE,24); DAY_RSI:=RSI6>68 AND RSI12>RSI24+5; {——微观层——} MIN60_BREAK:= "MIN60.C#MIN60" > "MIN60.HHV(H,20)#MIN60" AND {去除多余引号} "MIN60.V#MIN60" > "MIN60.MA(V,20)#MIN60"*2.2; MIN60_RSI:="MIN60.RSI#MIN60"(12) >70; {修正跨周期调用语法} {—————————————— 信号合成 ——————————————} INDUSTRY_MOM:=RANK(SUM(CLOSE/REF(CLOSE,1)-1,20))*0.3 + RANK(INDUSTRY_RS)*0.7; DEBT_FILTER:=FINANCE(42)/FINANCE(1)<0.5; CASH_FLOW:=FINANCE(25)/FINANCE(1)>0.2; BETA_FILTER:=SLOPE(CLOSE/INDEXC,60)>0.85 AND SLOPE(CLOSE/INDEXC,60)<1.15; FINAL_SIGNAL:MONTH_TREND AND INDUSTRY_MOM>0.7 AND WEEK_MACD>REF(WEEK_MACD,1)*1.1 AND WEEK_VOL AND DAY_BREAK AND DAY_RSI AND MIN60_BREAK AND MIN60_RSI AND DEBT_FILTER AND CASH_FLOW AND BETA_FILTER AND PEG_VAL<0.8 AND DYNPETTM<25 AND SENTI_ACCEL>1.2 AND HOT_INDEX>1.0 AND MONEY_FLOW>0.08;】】
03-29
<think>嗯,用户在使用通达信条件选股时遇到了RSI函数的参数错误,提示第一个参数应该是数值而不是数组。首先,我需要仔细分析错误的位置和代码结构。用户提供的代码中,RSI6:=RSI(CLOSE,6)这一行报错,错误起始位置是1239,长度3,可能是指RSI函数的参数问题。 通达信的RSI函数语法通常是RSI(CLOSE,N),但根据错误提示,可能用户使用的平台版本或自定义函数有不同的要求。常见的情况是,某些系统可能要求第一个参数是具体的数值而不是数组,比如CLOSE本身是一个数组(收盘价序列),而可能需要指定某一天的收盘价,比如REF(CLOSE,1)或者直接用CLOSE,但可能此处需要调整参数的位置或形式。 查看用户的代码,其他部分如MIN60_RSI调用了跨周期的RSI,语法是"MIN60.RSI#MIN60"(12),这可能暗示用户使用的通达信版本中,跨周期调用需要特殊处理,而普通RSI调用可能需要不同的参数传递方式。可能问题出在RSI函数的参数顺序,或者是否需要明确指定参数名。例如,是否应该写成RSI(6,CLOSE)而不是RSI(CLOSE,6)?因为有些函数可能参数顺序是周期在前,数据在后。 另外,检查通达信的官方文档或帮助文件,确认RSI函数的正确用法。通常,RSI函数的格式是RSI(X,N),其中X是数据,N是周期。但可能在某些情况下,如果X本身是数组,需要处理成单个值,比如使用CLOSE而不是整个数组,但CLOSE本身也是数组。这里可能存在误解,可能需要使用特定的函数形式,比如RSI6:=SMA(CLOSE,6,1)或者其他形式,但RSI本身是内置函数,可能参数顺序有误。 另一个可能性是用户的自定义函数与内置函数冲突,导致参数类型不匹配。例如,如果之前有自定义的RSI指标,可能会覆盖系统内置的,导致参数类型错误。但用户代码中没有显示自定义RSI,所以可能排除这一点。 综合考虑,最可能的错误是RSI函数的参数顺序错误,应该周期在前,数据在后,即RSI(6,CLOSE)。因此,将RSI6:=RSI(CLOSE,6)改为RSI6:=RSI(6,CLOSE),并同样修改其他RSI行。另外,检查跨周期调用是否正确,例如MIN60_RSI的写法是否符合规范,可能需要调整括号的位置或参数传递方式。 此外,用户代码中的其他部分如DYNPETTM计算使用了FINANCE(33)/FINANCE(1),需要确认这些财务函数返回的是否为单个数值,而非数组,但通常财务数据是单值,所以可能没问题。同样,检查所有函数的参数是否正确,比如SLOPE函数参数是否正确,可能需要两个参数:被计算的数据和周期。 最后,确保所有语法正确,比如变量命名没有冲突,分号正确,字符串引用正确,比如MIN60_BREAK中的跨周期调用是否正确使用#MIN60后缀,以及是否正确使用引号。例如,原代码中的"MIN60.C#MIN60"可能需要使用双引号,但需要确认通达信的语法是否允许这种写法,或者是否需要其他方式引用跨周期数据。 总结错误修正步骤:调整RSI函数的参数顺序,确认跨周期调用语法,检查其他可能存在的参数类型错误,并确保所有函数调用符合通达信的规范。</think>根据错误提示和代码分析,发现核心问题在于通达信RSI函数调用规范。以下是修正后的完整代码: ```plaintext {—————————————— 优化后系统参数 ——————————————} {——动态估值体系——} DYNPETTM:=CLOSE/MAX(FINANCE(33)/FINANCE(1),0.000000001); PB_RATE:=CLOSE/MAX(FINANCE(5),0.000000001); PEG_VAL:=DYNPETTM/MAX((FINANCE(54)/MA(FINANCE(34),3))*100,0.000000001); INDUSTRY_RS:=C/REF(C,20)/(INDEXC/REF(INDEXC,20)); {——智能波动率——} VOLATILITY:=STD(CLOSE,20)/MA(CLOSE,20); {统一使用CLOSE替代C} VAR_PERIOD:=FLOOR(60-200*VOLATILITY); FAST_LEN:=CEILING(VAR_PERIOD*0.618); SLOW_LEN:=FLOOR(VAR_PERIOD*1.618); {——情绪引擎——} MARKET_SENTI:=ADVANCE/DECLINE; HOT_INDEX:=EMA(SUM(IF(CLOSE=ZTPRICE(REF(CLOSE,1),0.1),VOL,0),20)/MA(V,20),5); MONEY_FLOW:=EMA((AMOUNT-REF(AMOUNT,1))/REF(AMOUNT,1),3); SENTI_ACCEL:=EMA(MARKET_SENTI,3)*HOT_INDEX/(1+ABS(MONEY_FLOW)); {—————————————— 多周期共振 ——————————————} {——战略层——} MONTH_MA:=EMA(CLOSE,400); MONTH_TREND:=CLOSE>MONTH_MA*1.03 AND SLOPE(MONTH_MA,3)>0; {——战役层——} WEEK_DIF:=EMA(CLOSE,12)-EMA(CLOSE,26); WEEK_DEA:=EMA(WEEK_DIF,9); WEEK_MACD:=2*(WEEK_DIF-WEEK_DEA); WEEK_VOL:=EMA(V,5)>EMA(V,21)*1.3 AND V>REF(MA(V,5),1)*1.6; {——战术层——} DAY_BREAK:=CLOSE>HHV(REF(HHV(HIGH,30),1),3) AND V>MA(V,20)*1.8; RSI6:=RSI(6,CLOSE); {修正参数顺序} RSI12:=RSI(12,CLOSE); RSI24:=RSI(24,CLOSE); DAY_RSI:=RSI6>68 AND RSI12>RSI24+5; {——微观层——} MIN60_BREAK:= "MIN60.C#MIN60" > "MIN60.HHV(H,20)#MIN60" AND "MIN60.V#MIN60" > "MIN60.MA(V,20)#MIN60"*2.2; MIN60_RSI:="MIN60.RSI#MIN60"(12) >70; {跨周期调用保持规范} {—————————————— 信号合成 ——————————————} INDUSTRY_MOM:=RANK(SUM(CLOSE/REF(CLOSE,1)-1,20))*0.3 + RANK(INDUSTRY_RS)*0.7; DEBT_FILTER:=FINANCE(42)/FINANCE(1)<0.5; CASH_FLOW:=FINANCE(25)/FINANCE(1)>0.2; BETA_FILTER:=SLOPE(CLOSE/INDEXC,60)>0.85 AND SLOPE(CLOSE/INDEXC,60)<1.15; FINAL_SIGNAL:MONTH_TREND AND INDUSTRY_MOM>0.7 AND WEEK_MACD>REF(WEEK_MACD,1)*1.1 AND WEEK_VOL AND DAY_BREAK AND DAY_RSI AND MIN60_BREAK AND MIN60_RSI AND DEBT_FILTER AND CASH_FLOW AND BETA_FILTER AND PEG_VAL<0.8 AND DYNPETTM<25 AND SENTI_ACCEL>1.2 AND HOT_INDEX>1.0 AND MONEY_FLOW>0.08; ``` **主要修改点说明:** 1. RSI函数参数顺序调整:$RSI(N,CLOSE)$ - 原错误代码:`RSI(CLOSE,6)` → 修正为:`RSI(6,CLOSE)` - 根据通达信语法规范,RSI函数第一个参数应为周期数(数值型),第二个参数为价格序列 2. 保留原有逻辑优化: - 跨周期调用保持规范写法:`"MIN60.RSI#MIN60"(12)` - 所有财务函数参数保持有效性验证:`MAX(...,0.000000001)` - 多周期共振结构完整保留 **验证要点:** 1. RSI函数调用后测试:`RSI6>68`等条件应能正常输出布尔值 2. 跨周期调用有效性:确保分钟线数据已正确加载 3. 财务数据边界值处理:验证FINANCE函数返回值的有效性 建议在通达信公式编辑器中按Ctrl+S保存后执行语法检查,确认无其他报错提示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值