龙空技术网

天池×九章算法|超级码力在线编程大赛 第2场题解

阿里云开发者 172

前言:

当前咱们对“java实现三角形的面积”大概比较讲究,同学们都想要剖析一些“java实现三角形的面积”的相关文章。那么小编也在网摘上网罗了一些对于“java实现三角形的面积””的相关资讯,希望朋友们能喜欢,姐妹们快快来了解一下吧!

1. 区间异或算法:st+rmq算法思路

根据题意,需要多次查询某区间的最大/最小值,那么我们可以考虑预处理st表,然后通过rmq快速查询某个区间的最大最小值

预处理(以区间最大值为例):

设$F[i][j]$表示数列A从第i个数起连续$2^j$个数$([i,i+2^j−1])$中的最大值。递推边界是$F[i][0] = A[i]$,即数列A在区间$[i,i]$里的最大值。在递推时,我们把子区间的长度成倍增加,即长度为$2^j$的子区间最大值是左右两半长度为$2^j$的子区间的最大值中较大的一个。即$Fi=max(Fi,Fi+2^j−1)$区间最小值同理

查询:

假如我们需要查询的区间为$[i, j]$,那么我们需要找到覆盖这个闭区间(左边界取i,右边界取j)。可以重复,比如查询5,6,7,8,9,我们可以查询5678和6789.因为这个区间的长度为$j-i+1$,所以我们可以取$k=log_2{(j−i+1)}$,则有$F[i,j]=max(F[i,k],F[j−2^k+1,k])$复杂度分析时间复杂度为$O(n*logn)$

+ $n$为数组的长度,rmq查询时间复杂度为$O(1)$空间复杂度为$O(n)$

+ $n$为数组的长度题解

C++

// This solution is powered by @lintcode.comclass Solution {public:    /**     * @param num: Array of num     * @param ask: Interval pairs     * @return: return the sum of xor     */    void st(int n) {        int k = (int)(log(n) / log(2.0));        for (int j = 1; j <= k; j++) {            for (int i = 0; i + (1 << j) - 1 < n; i++) {                intervalMax[i][j] = max(intervalMax[i][j - 1], intervalMax[i + (1 << (j - 1))][j - 1]);                intervalMin[i][j] = min(intervalMin[i][j - 1], intervalMin[i + (1 << (j - 1))][j - 1]);            }        }    }    int rmq(int l,int r,int flag){        int k = (int)(log(r - l + 1.0) / log(2.0));        if(flag)            return max(intervalMax[l][k], intervalMax[r - (1 << k) + 1][k]);        else            return min(intervalMin[l][k], intervalMin[r - (1 << k) + 1][k]);    }    int sumInterval(int l1,int r1,int l2,int r2) {        return rmq(l1,r1,1) + rmq(l2,r2,0);    }    int Intervalxor(vector<int> &num, vector<vector<int>> &ask) {        int n = num.size();        intervalMin.resize(n + 1);        intervalMax.resize(n + 1);        for (int i  = 0; i <= n; ++i) {            intervalMin[i].resize(30);            intervalMax[i].resize(30);        }        for(int i = 0; i < n; i++) {            intervalMin[i][0] = num[i];            intervalMax[i][0] = num[i];        }        st(n);        int ans = 0;        for (int i = 0;i < ask.size(); i++) {            int l1,r1,l2,r2;            l1 = ask[i][0] - 1;            r1 = ask[i][1] - 1;            l2 = ask[i][2] - 1;            r2 = ask[i][3] - 1;            ans ^= sumInterval(l1,r1,l2,r2);        }        return ans;    }private:    vector<vector<int> >intervalMax;    vector<vector<int> >intervalMin;};

Python

# This solution is powered by @lintcode.comimport mathclass Solution:    """    @param num: Array of num    @param ask: Interval pairs    @return: return the sum of xor    """    def st(self,n):        k = (int)(math.log(n) / math.log(2.0)) + 1        for j in range(1,k):            i = 0            while i + (1 << j) - 1 < n:                self.interval_max[i][j] = max(self.interval_max[i][j - 1], self.interval_max[i + (1 << (j - 1))][j - 1]);                self.interval_min[i][j] = min(self.interval_min[i][j - 1], self.interval_min[i + (1 << (j - 1))][j - 1]);                i += 1    def rmq(self,l,r,flag):        k = (int)(math.log(r - l + 1.0) / math.log(2.0))        if flag:            return max(self.interval_max[l][k], self.interval_max[r - (1 << k) + 1][k]);        else:            return min(self.interval_min[l][k], self.interval_min[r - (1 << k) + 1][k]);    def sum_interval(self,l1,r1,l2,r2):        return self.rmq(l1,r1,1) + self.rmq(l2,r2,0)    def Intervalxor(self, num, ask):        n = len(num);        self.interval_min = [[0 for _ in range(30)] for _ in range(n + 1)]        self.interval_max = [[0 for _ in range(30)] for _ in range(n + 1)]        for i in range(n):            self.interval_min[i][0] = num[i]            self.interval_max[i][0] = num[i]        self.st(n)        ans = 0        for interval in ask:            l1 = interval[0] - 1            r1 = interval[1] - 1            l2 = interval[2] - 1            r2 = interval[3] - 1            ans ^= self.sum_interval(l1,r1,l2,r2)        return ans;

Java题解详见:九章solution

2. 五字回文算法:模拟算法思路

根据题意,只要从头到尾判断长度为5的子串是否是五字回文

仔细观察给定数据,只有如abcba这种前三个不同的回文串才是符合题意的

那么每取一个长度为5的串就判断一下这个串是否符合条件五字回文的条件即可

复杂度分析时间复杂度为$O(n)$

+ $n$为字符串的长度空间复杂度为$O(1)$

+ 常量级额外空间题解

C++

// This solution is powered by @lintcode.comclass Solution {public:    bool isPalindrome(string s) {        if (s[0] != s[4] || s[1] != s[3]) {            return false;        }        if (s[0] == s[1] || s[1] == s[2] || s[0] == s[2]) {            return false;        }        return true;    }    int Fivecharacterpalindrome(string &s) {        int len = s.size();        if (len < 5) {            return 0;        }        int ans = 0;        for (int i = 0;i < len - 4;i++) {            if (isPalindrome(s.substr(i,5))) {                ans++;            }        }        return ans;    }};

Python

# This solution is powered by @lintcode.comclass Solution:    def is_palindrome(self,s):        if s[0] != s[4] or s[1] != s[3]:            return False        if s[0] == s[1] or s[1] == s[2] or s[0] == s[2]:            return False        return True;    def Fivecharacterpalindrome(self, s):        Len = len(s)        if Len < 5:            return 0        ans = 0;        for i in range(Len - 4):            if self.is_palindrome(s[i:i + 5]):                ans += 1        return ans

Java题解详见:九章solution

3. 三角魔法算法:几何算法思路

根据题意,只要给定点在给定的三个点构成的三角形中,那么就输出Yes

一个点在三角形内时,他与三个顶点可以构成三个三角形,这三个三角形的面积和等于原三角形的面积,同理如果点在三角形边上时也可以这样计算

同时记得特判三个点不构成三角形的情况,比如三点共线的情况。

复杂度分析时间复杂度为$O(1)$空间复杂度为$O(1)$题解

C++

// This solution is powered by @lintcode.comclass Solution {public:    typedef long long ll;    double triangleArea(int x1,int y1,int x2,int y2,int x3,int y3){        return abs((double)x1 * y2 + (double)y1 * x3 + (double)x2 * y3 -             (double)y2 * x3 - (double)y3 * x1 - (double)y1 * x2) / 2.0;     }    string castMagic(vector<vector<int>> &triangle, vector<int> &point) {        int x1 = triangle[0][0], y1 = triangle[0][1];        int x2 = triangle[1][0], y2 = triangle[1][1];        int x3 = triangle[2][0], y3 = triangle[2][1];        int p1 = point[0],p2 = point[1];        double sumArea = triangleArea(x1,y1,x2,y2,x3,y3);        if (sumArea == 0) {            return "No";        }        double area1 = triangleArea(x1,y1,x2,y2,p1,p2);        double area2 = triangleArea(x1,y1,x3,y3,p1,p2);        double area3 = triangleArea(x2,y2,x3,y3,p1,p2);        if(area1 + area2 + area3 == sumArea) {            return "Yes";        }        return "No";    }};

Python

# This solution is powered by @lintcode.comclass Solution:    def triangleArea(self,x1,y1,x2,y2,x3,y3):        return abs(x1 * y2 + y1 * x3 + x2 * y3 - y2 * x3 - y3 * x1 - y1 * x2) / 2.0    def castMagic(self, triangle, point):        x1,y1 = triangle[0][0], triangle[0][1]        x2,y2 = triangle[1][0], triangle[1][1]        x3,y3 = triangle[2][0], triangle[2][1]        p1,p2 = point[0], point[1];        sumArea = self.triangleArea(x1,y1,x2,y2,x3,y3)        if sumArea == 0:            return "No"        area1 = self.triangleArea(x1,y1,x2,y2,p1,p2)        area2 = self.triangleArea(x1,y1,x3,y3,p1,p2)        area3 = self.triangleArea(x2,y2,x3,y3,p1,p2)        if area1 + area2 + area3 == sumArea:            return "Yes"        return "No"

Java题解详见:九章solution

4. 小栖的金字塔算法:超级卡特兰数(大施罗德数)算法思路

假设从$[1,1]$按照题目思路到$[n,n]$,手推前几项,可以发现他符合施罗德数

施罗德数的递推公式为$F_n = F_{n-1} + \sum_{k=0}^{n-1}{F_{k}*F_{n-1-k}}\$,显然直接按照这个公式暴力递推会超时,所以我们引入超级卡特兰数,施罗德数恰好是他的的2倍关系($(F[1])$除外)

超级卡特兰数的递推公式:$F_n * (n+1) = (6*n-3)*F_{n-1}-(n-2)*F_{n-2}$,利用这个公式,就可以$O(n)$的时间内推出第n项超级卡特兰数

根据题意很容易发现,由于题目的限制,无论$[k,k]$在哪儿,到达$[n,n]$的路径都是一个小金字塔,那么我们只要现预处理$F_n$序列,然后直接计算$F_{n-k}$的值即可

复杂度分析时间复杂度为$O(n)$$n$为金字塔的层数,查询时间复杂度为$O(1)$空间复杂度为$O(n)$$n$为金字塔的层数题解

C++

// This solution is powered by @lintcode.comclass Solution {public:    typedef long long ll;    ll mod = 1e9 + 7;    ll inverse(ll x,ll y){        ll sum = 1;        while(y > 0){            if(y%2==1){                sum = sum * x % mod;            }            y /= 2;            x = x * x % mod;        }        return sum % mod;    }    int pyramid(int n, vector<int> &k) {        vector<ll> catalan(n + 1);        catalan[0] = 1;        catalan[1] = 1;        for(int i = 2; i <= n; i++){            catalan[i] = ((6 * i - 3) * catalan[i - 1] % mod - (i - 2) * catalan[i - 2] % mod + mod) % mod * inverse(i + 1,mod - 2) % mod;            cout<<catalan[i]<<endl;        }        ll ans = 0;        for(auto m:k){            if(n - m == 0){                ans += 1;                ans %= mod;                continue;            }            ans += catalan[n - m] * 2;            ans %= mod;        }        return ans;    }};

Python

# This solution is powered by @lintcode.comMOD = 1000000007class Solution:    def inverse(self,x,y):        sum = 1        while y > 0:            if y % 2 == 1:                sum = sum * x % MOD            y //= 2            x = x * x % MOD        return sum % MOD    def pyramid(self, n, k):        catalan = [1] * (n + 1)        for i in range(2,n + 1):            catalan[i] = ((6 * i - 3) * catalan[i - 1] % MOD - (i - 2) * catalan[i - 2] % MOD + MOD) % MOD * self.inverse(i + 1,MOD - 2) % MOD;        ans = 0        for m in k:            if n - m == 0:                ans += 1;                ans %= MOD;                continue;            ans += catalan[n - m] * 2;            ans %= MOD;        return ans;

标签: #java实现三角形的面积