一些零散的算法

C++常用数学函数

cpp 复制代码
#include<iostream>
#include<cmath>
using namespace std;

int main() {
    double x = 4.0, y = 2.0;

    // 平方根
    std::cout << "sqrt(" << x << ") = " << sqrt(x) << std::endl; //sqrt(4) = 2

    // 幂函数
    std::cout << "pow(" << x << ", " << y << ") = " << pow(x, y) << std::endl; 
    //pow(4, 2) = 16

    // 指数函数 (e 的 x 次幂)
    std::cout << "exp(" << x << ") = " << exp(x) << std::endl; //exp(4) = 54.5982

    // 以 2 为底的对数
    std::cout << "log2(" << x << ") = " << log2(x) << std::endl;

    // 自然对数
    std::cout << "log(" << x << ") = " << log(x) << std::endl; //log(4) = 1.38629

    // 常用对数(以10为底)
    std::cout << "log10(100) = " << log10(100) << std::endl; //log10(100) = 2

    double num = 3.7;

    // 向上取整 4
    std::cout << "ceil(" << num << ") = " << ceil(num) << std::endl;

    // 向下取整 3
    std::cout << "floor(" << num << ") = " << floor(num) << std::endl;

    // 四舍五入 4
    std::cout << "round(" << num << ") = " << round(num) << std::endl;

    // 向零取整(就是去掉小数部分) 3
    std::cout << "trunc(" << num << ") = " << trunc(num) << std::endl; 
    
    double angle = 45.0; // 角度
    const double M_PI = 3.14159265358979323846; 
    // M_PI 在某些编译环境中可能未定义。这是因为 M_PI 不是 C++ 标准的一部分
    double radian = angle * M_PI / 180.0; // 转换为弧度

    std::cout << "sin(" << angle << "°) = " << sin(radian) << std::endl;
    std::cout << "cos(" << angle << "°) = " << cos(radian) << std::endl;
    std::cout << "tan(" << angle << "°) = " << tan(radian) << std::endl;

    // 反三角函数
    double value = 0.5;
    std::cout << "asin(" << value << ") = " << asin(value)*180/M_PI << "°" << std::endl;
    std::cout << "acos(" << value << ") = " << acos(value)*180/M_PI << "°" << std::endl;
    std::cout << "atan(" << value << ") = " << atan(value)*180/M_PI << "°" << std::endl;

    int a = -10, b = 3;
    double c = -5.5;

    std::cout << "abs(" << a << ") = " << abs(a) << std::endl;        // 整数绝对值
    std::cout << "fabs(" << c << ") = " << fabs(c) << std::endl;      // 浮点数绝对值
    std::cout << "fmod(10.5, 3.2) = " << fmod(10.5, 3.2) << std::endl; // 浮点数取模
    return 0;
}

数组中两个目标值的最短距离

数组中两个字符串的最小距离__牛客网

给定一个字符串数组strs,再给定两个字符串str1和str2,返回在strs中str1和str2的最小距离,如果str1或str2为null,或不在strs中,返回-1。

解法:遍历数组的同时,用两个变量标记当前位置之前的最后出现的 str1 和 str2 的下标。

cpp 复制代码
#include <iostream>
#include <string>
#include <climits>
using namespace std;

int main()
{
    int n; cin >> n;
    string s1,s2;cin >> s1 >> s2;
    if(s1.size() == 0 || s2.size() == 0)
    {
        cout << -1 << endl;
        return 0;
    }

    int i1 = -1,i2 = -1;
    int ret = INT_MAX;
    for(int i = 1; i <= n; i++)
    {
        string t; cin >> t;
        if(t == s1)
        {
            if(i2 != -1) ret = min(ret,i - i2);
            i1 = i;
        }
        else if(t == s2)
        {
            if(i1 != -1) ret = min(ret,i - i1);
            i2 = i;
        }
    }

    if(ret == INT_MAX) cout << -1 << endl;
    else cout << ret << endl;
    return 0;
}

两个链表的第一个公共结点

除了统计两个链表的长度,然后让长的链表的指针先走之外,还可以采用这种方式:cur1 和 cur2 同时从头结点出发,如果 cur1 为空(到末尾了),就将 cur1 重新从另一个链表的头节点开始遍历,cur2 同理。运用了等量关系:x1 + x + x2 = x2 + x + x1,该解法和上面提到的解法都可以处理没有公共结点的情况

cpp 复制代码
/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
typedef long long LL;
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
    //     LL len1 = 0;
	// 	LL len2 = 0;
		
	// 	ListNode* cur = pHead1;
	// 	while(cur) 
	// 	{
	// 		if(cur)
	// 		{
	// 			len1++;
	// 			cur = cur->next;
	// 		}
	// 	}

	// 	cur = pHead2;
	// 	while(cur) 
	// 	{
	// 		if(cur)
	// 		{
	// 			len2++;
	// 			cur = cur->next;
	// 		}
	// 	}

	// 	ListNode* cur1 = pHead1;
	// 	ListNode* cur2 = pHead2;

	// 	if(len1 > len2) 
	// 	{
	// 		LL cnt = len1 - len2;
	// 		while(cnt--) cur1 = cur1->next;
	// 	}
	// 	else if(len2 > len1)
	// 	{
	// 		LL cnt = len2 - len1;
	// 		while(cnt--) cur2 = cur2->next;
	// 	}

	// 	while(cur1 != cur2) 
	// 	{
	// 		cur1 = cur1->next;
	// 		cur2 = cur2->next;
	// 	}

	// 	return cur1;

		ListNode* cur1 = pHead1;
		ListNode* cur2 = pHead2;
		while(cur1 != cur2)
		{
			if(cur1) cur1 = cur1->next;
			else cur1 = pHead2;

			if(cur2) cur2 = cur2->next;
			else cur2 = pHead1;
		}

		return cur1;

    }


};

判断一个数是否是 2 的 n 次方

  • 方法1:不断除 2,最终会变成 1
  • 方法2:二进制表示只有一个"1",其余位都是"0" ----> 统计二进制表示"1" 的个数
  • 方法3:在方法 2 的基础之上,进行 lowbit 操作:假设要判断的数是 x,如果 x - (x & -x) == 0 成立,则 x 是 2 的 n 次方,否则不是
  • 方法4:在方法 2 的基础之上,假设要判断的数是 x,如果 x & (x - 1) == 0成立,则 x 是 2 的 n 次方,否则不是

n 条线段的最多重叠次数

题目描述:给出 n 条线段的起始坐标和结束坐标,判断这 n 条线段的最多重叠次数。

解析:1、先按照这 n 条线段的起始坐标排序,2、创建一个小根堆,3、从左往右依次遍历线段

最长上升子序列(贪心 + 二分)

这道题是动态规划的经典题目,但它有一个更优的解法,时间复杂度为 nlogn,这个解法是贪心 + 二分。解法:依次遍历数组,在遍历的过程中,我们只需要知道:长度为 1 的上升子序列的末尾元素、长度为 2 的上升子序列的末尾元素、长度为 3 的上升子序列的末尾元素等等,把这些末尾元素记录在 t 数组中,t[i] 表示长度为 i 的上升子序列的末尾元素,现在假设遍历到了一个新的元素 m ,我们就把该元素与上面记录的末尾元素比较,如果 m > t[i] ,说明 m 可以接在 t[i] 后面形成长度为 i + 1 的上升子序列,再把 m 与 t[i + 1] 比较,如果 m > t[i + 1] 仍然成立,说明 m 可以接在 t[i + 1] 后面形成长度为 i + 2 的上升子序列,就这样从 t 数组的首元素依次比较,直到 i <= t[j],说明 i 可以接在 t[j - 1] 后面形成长度为 j 的上升子序列,并且把 i 赋值给 t[j] ,因为 i <= t[j],这样做可以让后面要遍历的元素更有机会接在 j 的后面,因为 t[j] 变成一个比较小的数字 i 了,这是体现贪心的地方。我们在比较 i 与 t 数组的元素关系时,采用顺序遍历,其实可以用二分查找 i 的插入位置,i 插入位置其实就是 t[j] < i 与 t[j] >= i 的分界点。

在下面的代码中,由于二分查找需要确定待查找区间的左右端点,刚开始查找时,左端点是 0,右端点是 ret + 1,ret 就是最长上升子序列的长度,如果最后找到的插入位置是 ret + 1,那么 ret++

cpp 复制代码
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 该数组最长严格上升子序列的长度
     * @param a int整型vector 给定的数组
     * @return int整型
     */
    static const int N = 1e5 + 10;
    int t[N];
    int LIS(vector<int>& a) {
        // write code here

        // dp
        // int sz = a.size();
        // if(sz == 0) return 0;
        // for(int i = 0; i < sz; i++) dp[i] = 1;

        // for(int i = 1; i < sz; i++)
        // {
        //     for(int j = 0; j < i; j++)
        //     {
        //         if(a[j] < a[i]) dp[i] = max(dp[i],dp[j] + 1);
        //     }
        // } 

        // int ret = 1;
        // for(int i = 0; i < sz; i++) ret = max(ret,dp[i]);
        // return ret;


        // 贪心 + 二分
        int sz = a.size();
        if(sz == 0) return 0;
        memset(t,0x3f,sizeof(t));

        t[1] = a[0];
        int ret = 1;

        for(int i = 1; i < sz; i++)
        {
            int l = 1;
            int r = ret + 1;
            while(l < r)
            {
                int mid = l + (r - l) / 2;
                if(t[mid] < a[i]) l = mid + 1;
                else r = mid;
            }

            t[l] = a[i];
            if(l == ret + 1) ret++;
        }

        return ret;
    }
};
相关推荐
khalil10201 小时前
代码随想录算法训练营Day-48 单调栈02 | 42. 接雨水、84.柱状图中最大的矩形
数据结构·c++·算法·leetcode·单调栈·接雨水
Hcoco_me1 小时前
Ai:Agent/ infra / 智驾 / 推广算法 题库
人工智能·深度学习·算法·自动驾驶·剪枝
项目申报小狂人1 小时前
提出了一种带双向搜索的粒子群优化算法,一种基于双四元数运动优化的新型无人机3D路径规划方法及应用
算法·3d·无人机
驼同学.1 小时前
牛客网面试TOP101 - Python算法学习指南
python·算法·面试
大大杰哥1 小时前
leetcode hot100(3)子串
c++·算法·leetcode
fish_xk1 小时前
哈希的了解
算法·哈希算法
水木流年追梦1 小时前
大模型入门-应用篇1-prompt技术
开发语言·python·算法·prompt
莫生灬灬1 小时前
ElementUI封装 共91个组件 支持易语言/火山/C#/Python
开发语言·c++·python·ui·elementui·c#
WL_Aurora1 小时前
【每日一题】位运算
python·算法