Acy夕拾算法 Week2_day3

LeetCode 46. 全排列

/*
整理思路:
无重复元素;排列,元素有顺序
代码随想录
元素不能重复使用,used记录:使用过的-true
树形结构;数组的大小为树的深度
for循环根据used横向遍历;递归根据 结果与数组的大小相等 结束纵向遍历
结果在叶子节点上
*/

//代码随想录
class Solution {
public:
    vector<int> path;
    vector<vector<int>> res;

    void backtracking(vector<int>& nums, vector<bool>& used)
    {
        if(path.size() == nums.size())
        {
            res.push_back(path);
            return;
        }

        for(int i = 0; i < nums.size(); i++)
        {
            if(used[i] == true) continue;
            path.push_back(nums[i]);
            used[i] = true;
            backtracking(nums, used);
            path.pop_back();//回溯
            used[i] = false;
        }
    }

    vector<vector<int>> permute(vector<int>& nums) {
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return res;
    }
};

LeetCode 78. 子集

/*
整理思路:
集合,无重复,顺序改变不增加子集个数
树形结构
startIndex控制从数组的哪里开始取数
结果在每个节点里,每层递归都收集结果
*/

class Solution {
public:
    vector<int> path;
    vector<vector<int>> res;

    void backtracking(vector<int>& nums, int startIndex)
    {
        res.push_back(path);

        for(int i = startIndex; i < nums.size(); i++)
        {
            path.push_back(nums[i]);
            backtracking(nums, i+1);//取数位置后移
            path.pop_back();
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums, 0);
        return res;
    }
};

LeetCode 39. 组合总和

/*
整理思路:
可重复加,选完仍可再选
代码随想录:回溯三部曲
1.确定函数参数和返回值:sum保存path中元素的和;startIndex数组取数开始位置
2.确定递归终止条件:如果sum>target不继续return;等于push
3.单层搜索逻辑:更新元素至数组中;sum+=;元素可重复使用,递归时用i即可;如何收集如何吐
*/

class Solution {
public:
    vector<int> path;
    vector<vector<int>> res;

    void backtracking(vector<int>& nums, int target, int sum, int startIndex)
    {
        if(sum > target)    return;
        if(sum == target)
        {
            res.push_back(path);
            return;
        }

        for(int i = startIndex; i < nums.size(); i++)
        {
            sum += nums[i];
            path.push_back(nums[i]);
            backtracking(nums, target, sum, i);
            sum -= nums[i];
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        backtracking(candidates, target, 0, 0);
        return res;
    }
};
### Java实现Delaunay三角剖分算法 Delaunay三角剖分是一种在二维空间中对点集进行三角化的方法,其核心特性是:任意两个点之间的边不会与其他边相交,并且每个三角形的外接圆内不包含其他点。这种特性使得Delaunay三角剖分广泛应用于计算机图形学、地理信息系统(GIS)等领域。 在Java中实现Delaunay三角剖分,通常可以采用**增量插入法**(Bowyer-Watson算法),该算法通过逐步插入点并删除与新点冲突的三角形来维护Delaunay性质。以下是一个基于该算法的Java实现示例。 --- ### Java代码实现 ```java import java.util.*; class Point { double x, y; Point(double x, double y) { this.x = x; this.y = y; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Point)) return false; Point other = (Point) obj; return Double.compare(other.x, x) == 0 && Double.compare(other.y, y) == 0; } @Override public int hashCode() { return Objects.hash(x, y); } } class Triangle { Point a, b, c; Set<Edge> edges = new HashSet<>(); Triangle(Point a, Point b, Point c) { this.a = a; this.b = b; this.c = c; edges.add(new Edge(a, b)); edges.add(new Edge(b, c)); edges.add(new Edge(c, a)); } boolean circumcircleContains(Point p) { double abx = a.x - b.x; double aby = a.y - b.y; double acx = a.x - c.x; double acy = a.y - c.y; double d = 2 * (abx * (a.y - c.y) - acx * aby); double cx_ = ( (a.x * a.x - b.x * b.x) * (a.y - c.y) - (a.x * a.x - c.x * c.x) * aby ) / d; double cy_ = ( (a.y * a.y - b.y * b.y) * (abx) - (a.y * a.y - c.y * c.y) * acx ) / d; double r = Math.sqrt((a.x - cx_) * (a.x - cx_) + (a.y - cy_) * (a.y - cy_)); double px = p.x - cx_; double py = p.y - cy_; return (px * px + py * py) <= r * r + 1e-8; } } class Edge { Point p1, p2; Edge(Point p1, Point p2) { if (p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y)) { this.p1 = p1; this.p2 = p2; } else { this.p1 = p2; this.p2 = p1; } } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Edge)) return false; Edge other = (Edge) obj; return p1.equals(other.p1) && p2.equals(other.p2); } @Override public int hashCode() { return Objects.hash(p1, p2); } } public class DelaunayTriangulation { private static List<Triangle> triangulate(List<Point> points) { List<Triangle> triangles = new ArrayList<>(); Point p1 = new Point(-1000, -1000); Point p2 = new Point(1000, -1000); Point p3 = new Point(0, 1000); Triangle superTriangle = new Triangle(p1, p2, p3); triangles.add(superTriangle); for (Point p : points) { Set<Edge> polygon = new HashSet<>(); List<Triangle> badTriangles = new ArrayList<>(); for (Triangle t : triangles) { if (t.circumcircleContains(p)) { badTriangles.add(t); for (Edge e : t.edges) { boolean shared = false; for (Triangle other : triangles) { if (other != t && other.edges.contains(e)) { shared = true; break; } } if (!shared) { polygon.add(e); } } } } for (Edge e : polygon) { triangles.add(new Triangle(e.p1, e.p2, p)); } triangles.removeAll(badTriangles); } // 移除包含超级三角形顶点的三角形 triangles.removeIf(t -> t.a == p1 || t.a == p2 || t.a == p3 || t.b == p1 || t.b == p2 || t.b == p3 || t.c == p1 || t.c == p2 || t.c == p3); return triangles; } public static void main(String[] args) { List<Point> points = new ArrayList<>(); points.add(new Point(0.0, 0.0)); points.add(new Point(1.0, 0.0)); points.add(new Point(0.5, 1.0)); points.add(new Point(0.5, 0.5)); List<Triangle> result = triangulate(points); for (Triangle t : result) { System.out.println("Triangle: (" + t.a.x + "," + t.a.y + ") - (" + t.b.x + "," + t.b.y + ") - (" + t.c.x + "," + t.c.y + ")"); } } } ``` --- ### 代码说明 - **Point类**:表示二维空间中的点。 - **Edge类**:表示三角形的边,用于边去重。 - **Triangle类**:表示一个三角形,并包含判断点是否在三角形外接圆内的方法。 - **triangulate方法**:使用Bowyer-Watson算法进行增量插入,构建Delaunay三角剖分。 - **main方法**:提供测试点集并输出三角剖分结果。 该实现能够处理任意二维点集,并输出符合Delaunay条件的三角形集合。算法的时间复杂度为O(n&sup2;),适用于中等规模的数据集。 --- ### 性能优化与扩展 对于大规模点集,可以引入**分治法**或**平面扫描法**来提升性能。此外,该算法也可以扩展到三维空间,形成**三维Delaunay三角剖分**(Tetrahedralization),但实现复杂度显著增加[^3]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值