如果一个问题具有传递性,则考虑使用并查集!
399.除法求值
399-除法求值
class Solution {
public double [ ] calcEquation ( List < List < String > > equations, double [ ] values, List < List < String > > queries) {
int equationsSize = equations. size ( ) ;
UnionFind unionFind = new UnionFind ( 2 * equationsSize) ;
Map < String , Integer > map = new HashMap < > ( 2 * equationsSize) ;
int id = 0 ;
for ( int i = 0 ; i < equationsSize; i++ ) {
String s1 = equations. get ( i) . get ( 0 ) ;
String s2 = equations. get ( i) . get ( 1 ) ;
if ( ! map. containsKey ( s1) ) {
map. put ( s1, id++ ) ;
}
if ( ! map. containsKey ( s2) ) {
map. put ( s2, id++ ) ;
}
unionFind. union ( map. get ( s1) , map. get ( s2) , values[ i] ) ;
}
int queriesSize = queries. size ( ) ;
double [ ] ans = new double [ queriesSize] ;
for ( int i = 0 ; i < queriesSize; i++ ) {
String s1 = queries. get ( i) . get ( 0 ) ;
String s2 = queries. get ( i) . get ( 1 ) ;
Integer id1 = map. get ( s1) ;
Integer id2 = map. get ( s2) ;
if ( id1 == null || id2 == null )
ans[ i] = - 1.0d ;
else
ans[ i] = unionFind. isConnected ( id1, id2) ;
}
return ans;
}
private class UnionFind {
private int [ ] parent;
private double [ ] weight;
public UnionFind ( int size) {
parent = new int [ size] ;
weight = new double [ size] ;
for ( int i = 0 ; i < size; i++ ) {
parent[ i] = i;
weight[ i] = 1.0d ;
}
}
public void union ( int x, int y, double val) {
int rootX = find ( x) ;
int rootY = find ( y) ;
if ( rootX == rootY)
return ;
else {
parent[ rootX] = rootY;
weight[ rootX] = val * weight[ y] / weight[ x] ;
}
}
public int find ( int x) {
if ( parent[ x] != x) {
int origin = parent[ x] ;
parent[ x] = find ( parent[ x] ) ;
weight[ x] *= weight[ origin] ;
}
return parent[ x] ;
}
public double isConnected ( int x, int y) {
int rootX = find ( x) ;
int rootY = find ( y) ;
if ( rootX != rootY)
return - 1.0d ;
return weight[ x] / weight[ y] ;
}
}
}
990.等式方程的可满足性
990
class Solution {
public boolean equationsPossible ( String [ ] equations) {
int [ ] parent = new int [ 26 ] ;
for ( int i = 0 ; i < 26 ; i++ ) {
parent[ i] = i;
}
for ( String s : equations) {
if ( s. charAt ( 1 ) == '=' ) {
int id1 = s. charAt ( 0 ) - 'a' ;
int id2 = s. charAt ( 3 ) - 'a' ;
union ( parent, id1, id2) ;
}
}
for ( String s : equations) {
if ( s. charAt ( 1 ) == '!' ) {
int id1 = s. charAt ( 0 ) - 'a' ;
int id2 = s. charAt ( 3 ) - 'a' ;
if ( find ( parent, id1) == find ( parent, id2) )
return false ;
}
}
return true ;
}
public void union ( int [ ] parent, int x, int y) {
int rootX = find ( parent, x) ;
int rootY = find ( parent, y) ;
parent[ rootX] = rootY;
}
public int find ( int [ ] parent, int x) {
if ( parent[ x] != x) {
parent[ x] = find ( parent, parent[ x] ) ;
}
return parent[ x] ;
}
}
547.省份数量
547
class Solution {
public int findCircleNum ( int [ ] [ ] isConnected) {
int n = isConnected. length;
int [ ] parent = new int [ n] ;
for ( int i = 0 ; i < n; i++ ) {
parent[ i] = i;
}
Set < Integer > set = new HashSet < > ( ) ;
for ( int i = 0 ; i < n; i++ ) {
for ( int j = 0 ; j < n; j++ ) {
if ( isConnected[ i] [ j] == 1 && i != j) {
union ( parent, i, j) ;
}
}
}
int ans = 0 ;
for ( int i = 0 ; i < n; i++ ) {
if ( parent[ i] == i)
ans++ ;
}
return ans;
}
public void union ( int [ ] parent, int x, int y) {
parent[ find ( parent, x) ] = find ( parent, y) ;
}
public int find ( int [ ] parent, int x) {
if ( parent[ x] != x) {
parent[ x] = find ( parent, parent[ x] ) ;
}
return parent[ x] ;
}
}
1631.最小体力值消耗路径
1并查集
class Solution {
public int minimumEffortPath ( int [ ] [ ] heights) {
int m = heights. length, n = heights[ 0 ] . length;
List < int [ ] > edges = new ArrayList < > ( ) ;
for ( int i = 0 ; i < m; i++ ) {
for ( int j = 0 ; j < n; j++ ) {
int id = i * n + j;
if ( i < m- 1 )
edges. add ( new int [ ] { id, id+ n, Math . abs ( heights[ i+ 1 ] [ j] - heights[ i] [ j] ) } ) ;
if ( j < n- 1 )
edges. add ( new int [ ] { id, id+ 1 , Math . abs ( heights[ i] [ j+ 1 ] - heights[ i] [ j] ) } ) ;
}
}
Collections . sort ( edges, new Comparator < int [ ] > ( ) {
public int compare ( int [ ] edge1, int [ ] edge2) {
return edge1[ 2 ] - edge2[ 2 ] ;
}
} ) ;
UnionFind uf = new UnionFind ( m* n) ;
for ( int [ ] edge : edges) {
int id1 = edge[ 0 ] , id2 = edge[ 1 ] , weight = edge[ 2 ] ;
uf. union ( id1, id2) ;
if ( uf. connected ( 0 , m* n- 1 ) ) {
return weight;
}
}
return 0 ;
}
class UnionFind {
private int [ ] parent;
public UnionFind ( int n) {
parent = new int [ n] ;
for ( int i = 0 ; i < n; i++ ) {
parent[ i] = i;
}
}
public void union ( int x, int y) {
parent[ find ( x) ] = parent[ find ( y) ] ;
}
public int find ( int x) {
if ( x != parent[ x] ) {
parent[ x] = find ( parent[ x] ) ;
}
return parent[ x] ;
}
public boolean connected ( int x, int y) {
return find ( x) == find ( y) ;
}
}
}
最短路径算法—dijkstra算法变形
class Solution {
int [ ] [ ] dirs = { { - 1 , 0 } , { 1 , 0 } , { 0 , - 1 } , { 0 , 1 } } ;
public int minimumEffortPath ( int [ ] [ ] heights) {
int m = heights. length, n = heights[ 0 ] . length;
PriorityQueue < int [ ] > pq = new PriorityQueue < > ( new Comparator < int [ ] > ( ) {
public int compare ( int [ ] edge1, int [ ] edge2) {
return edge1[ 2 ] - edge2[ 2 ] ;
}
} ) ;
pq. offer ( new int [ ] { 0 , 0 , 0 } ) ;
int [ ] dist = new int [ m* n] ;
Arrays . fill ( dist, Integer . MAX_VALUE) ;
dist[ 0 ] = 0 ;
boolean [ ] seen = new boolean [ m* n] ;
while ( ! pq. isEmpty ( ) ) {
int [ ] edge = pq. poll ( ) ;
int x = edge[ 0 ] , y = edge[ 1 ] , d = edge[ 2 ] ;
int id = x* n+ y;
if ( seen[ id] )
continue ;
if ( x == m- 1 && y == n- 1 )
break ;
seen[ id] = true ;
for ( int i = 0 ; i < 4 ; i++ ) {
int nx = x + dirs[ i] [ 0 ] , ny = y + dirs[ i] [ 1 ] ;
if ( nx >= 0 && nx < m & & ny > = 0 && ny < n && Math . max ( d, Math . abs ( heights[ x] [ y] - heights[ nx] [ ny] ) ) < dist[ nx* n+ ny] ) {
dist[ nx* n+ ny] = Math . max ( d, Math . abs ( heights[ x] [ y] - heights[ nx] [ ny] ) ) ;
pq. offer ( new int [ ] { nx, ny, dist[ nx* n+ ny] } ) ;
}
}
}
return dist[ m* n- 1 ] ;
}
}