Convex Polygon Problem#
Problem#
Given a list of points that form a polygon when joined sequentially, find if this polygon is convex (Convex polygon definition) .
Note:
There are at least 3 and at most 10,000 points.
Coordinates are in the range -10,000 to 10,000.
You may assume the polygon formed by given points is always a simple polygon (Simple polygon definition) . In other words, we ensure that exactly two edges intersect at each vertex, and that edges otherwise don’t intersect each other .
Examples#
Example 1:
1
2
3
[[0,0],[0,1],[1,1],[1,0]]
Answer: True
Explanation:
Example 2:
1
2
3
[[0,0],[0,10],[10,10],[10,0],[5,5]]
Answer: False
Explanation:
Solution#
Method 1 – Cross Product Sign Consistency#
Intuition#
A polygon is convex if all its internal angles are less than 180 degrees. This is equivalent to saying that as we walk along the edges, the cross product of each pair of consecutive edges should have the same sign (all left turns or all right turns).
Approach#
For each triplet of consecutive points, compute the cross product of the vectors formed by these points.
Track the sign of the first non-zero cross product.
If any subsequent non-zero cross product has a different sign, the polygon is not convex.
If all non-zero cross products have the same sign, the polygon is convex.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public :
bool isConvex(vector< vector< int >>& p) {
int n = p.size(), sign = 0 ;
for (int i = 0 ; i < n; ++ i) {
int dx1 = p[(i+ 1 )% n][0 ] - p[i][0 ];
int dy1 = p[(i+ 1 )% n][1 ] - p[i][1 ];
int dx2 = p[(i+ 2 )% n][0 ] - p[(i+ 1 )% n][0 ];
int dy2 = p[(i+ 2 )% n][1 ] - p[(i+ 1 )% n][1 ];
int cross = dx1 * dy2 - dy1 * dx2;
if (cross != 0 ) {
if (sign == 0 ) sign = cross > 0 ? 1 : - 1 ;
else if ((cross > 0 ? 1 : - 1 ) != sign) return false;
}
}
return true;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func isConvex (p [][]int ) bool {
n , sign := len(p ), 0
for i := 0 ; i < n ; i ++ {
dx1 := p [(i + 1 )% n ][0 ] - p [i ][0 ]
dy1 := p [(i + 1 )% n ][1 ] - p [i ][1 ]
dx2 := p [(i + 2 )% n ][0 ] - p [(i + 1 )% n ][0 ]
dy2 := p [(i + 2 )% n ][1 ] - p [(i + 1 )% n ][1 ]
cross := dx1 * dy2 - dy1 * dx2
if cross != 0 {
if sign == 0 {
if cross > 0 { sign = 1 } else { sign = - 1 }
} else if (cross > 0 && sign < 0 ) || (cross < 0 && sign > 0 ) {
return false
}
}
}
return true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public boolean isConvex (int [][] p) {
int n = p.length , sign = 0;
for (int i = 0; i < n; i++ ) {
int dx1 = p[ (i+ 1)% n][ 0] - p[ i][ 0] ;
int dy1 = p[ (i+ 1)% n][ 1] - p[ i][ 1] ;
int dx2 = p[ (i+ 2)% n][ 0] - p[ (i+ 1)% n][ 0] ;
int dy2 = p[ (i+ 2)% n][ 1] - p[ (i+ 1)% n][ 1] ;
int cross = dx1 * dy2 - dy1 * dx2;
if (cross != 0) {
if (sign == 0) sign = cross > 0 ? 1 : - 1;
else if ((cross > 0 ? 1 : - 1) != sign) return false ;
}
}
return true ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
fun isConvex (p: Array<IntArray>): Boolean {
val n = p.size
var sign = 0
for (i in 0 until n) {
val dx1 = p[(i+1 )%n][0 ] - p[i][0 ]
val dy1 = p[(i+1 )%n][1 ] - p[i][1 ]
val dx2 = p[(i+2 )%n][0 ] - p[(i+1 )%n][0 ]
val dy2 = p[(i+2 )%n][1 ] - p[(i+1 )%n][1 ]
val cross = dx1 * dy2 - dy1 * dx2
if (cross != 0 ) {
if (sign == 0 ) sign = if (cross > 0 ) 1 else -1
else if ((cross > 0 && sign < 0 ) || (cross < 0 && sign > 0 )) return false
}
}
return true
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution :
def isConvex (self, p: list[list[int]]) -> bool:
n, sign = len(p), 0
for i in range(n):
dx1 = p[(i+ 1 )% n][0 ] - p[i][0 ]
dy1 = p[(i+ 1 )% n][1 ] - p[i][1 ]
dx2 = p[(i+ 2 )% n][0 ] - p[(i+ 1 )% n][0 ]
dy2 = p[(i+ 2 )% n][1 ] - p[(i+ 1 )% n][1 ]
cross = dx1 * dy2 - dy1 * dx2
if cross != 0 :
if sign == 0 :
sign = 1 if cross > 0 else - 1
elif (cross > 0 and sign < 0 ) or (cross < 0 and sign > 0 ):
return False
return True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
impl Solution {
pub fn is_convex (p: Vec< Vec< i32 >> ) -> bool {
let n = p.len();
let mut sign = 0 ;
for i in 0 .. n {
let dx1 = p[(i+ 1 )% n][0 ] - p[i][0 ];
let dy1 = p[(i+ 1 )% n][1 ] - p[i][1 ];
let dx2 = p[(i+ 2 )% n][0 ] - p[(i+ 1 )% n][0 ];
let dy2 = p[(i+ 2 )% n][1 ] - p[(i+ 1 )% n][1 ];
let cross = dx1 * dy2 - dy1 * dx2;
if cross != 0 {
if sign == 0 {
sign = if cross > 0 { 1 } else { - 1 };
} else if (cross > 0 && sign < 0 ) || (cross < 0 && sign > 0 ) {
return false ;
}
}
}
true
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
isConvex (p : number [][]): boolean {
let n = p .length , sign = 0 ;
for (let i = 0 ; i < n ; i ++ ) {
let dx1 = p [(i + 1 )% n ][0 ] - p [i ][0 ];
let dy1 = p [(i + 1 )% n ][1 ] - p [i ][1 ];
let dx2 = p [(i + 2 )% n ][0 ] - p [(i + 1 )% n ][0 ];
let dy2 = p [(i + 2 )% n ][1 ] - p [(i + 1 )% n ][1 ];
let cross = dx1 * dy2 - dy1 * dx2 ;
if (cross !== 0 ) {
if (sign === 0 ) sign = cross > 0 ? 1 : - 1 ;
else if ((cross > 0 && sign < 0 ) || (cross < 0 && sign > 0 )) return false ;
}
}
return true ;
}
}
Complexity#
⏰ Time complexity: O(n)
, where n is the number of points.
🧺 Space complexity: O(1)
, only constant extra space is used.