Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match girl has, please find out a way you can make one square by using up all those matchsticks. You should not break any stick, but you can link them up, and each matchstick must be used exactly one time.

Your input will be several matchsticks the girl has, represented with their stick length. Your output will either be true or false, to represent whether you could make one square using all the matchsticks the little match girl has.

Example 1:
Input: [1,1,2,2,2]
Output: true Explanation: You can form a square with length 2, one side of the square came two sticks with length 1.
Example 2:
Input: [3,3,3,3,4]
Output: false Explanation: You cannot find a way to form a square with all the matchsticks.
Note:
The length sum of the given matchsticks is in the range of 0 to 10^9.
The length of the given matchstick array will not exceed 15.

DFS, my solution is to fill each edge of the square one by one. DFS to construct the 1st, then 2nd, then 3rd, then 4th. For each edge I scan all the matches but only pick some, the others are discarded. These brings about two disadvantages: 1. I need to keep track of visited elem. 2. after the 1st edge is constructed, I have to re-scan to make the 2nd, 3rd, 4th, thus waste time! So my code get TLE in big case

 public class Solution {
public boolean makesquare(int[] nums) {
if (nums==null || nums.length==0) return false;
int sideLen = 0;
for (int num : nums) {
sideLen += num;
}
if (sideLen % 4 != 0) return false;
sideLen /= 4;
return find(nums, sideLen, 0, 0, new HashSet<Integer>());
} public boolean find(int[] nums, int sideLen, int completed, int curLen, HashSet<Integer> visited) {
if (curLen > sideLen) return false;
if (curLen == sideLen) {
completed++;
curLen = 0;
if (completed==4 && visited.size()==nums.length) return true;
if (completed==4 && visited.size()<nums.length) return false;
}
for (int i=0; i<nums.length; i++) {
if (!visited.contains(i)) {
visited.add(i);
if (find(nums, sideLen, completed, curLen+nums[i], visited))
return true;
visited.remove(i);
}
}
return false;
}
}

Better Solution: DFS, but only scan all the matches once! If a match can not make the 1st edge, then we do not discard it, we try 2nd, 3rd, 4th edge

referred to: https://discuss.leetcode.com/topic/72107/java-dfs-solution-with-explanation

 public class Solution {
public boolean makesquare(int[] nums) {
if (nums == null || nums.length < 4) return false;
int sum = 0;
for (int num : nums) sum += num;
if (sum % 4 != 0) return false; return dfs(nums, new int[4], 0, sum / 4);
} private boolean dfs(int[] nums, int[] sums, int index, int target) {
if (index == nums.length) {
if (sums[0] == target && sums[1] == target && sums[2] == target) {
return true;
}
return false;
} for (int i = 0; i < 4; i++) {
if (sums[i] + nums[index] > target) continue;
sums[i] += nums[index];
if (dfs(nums, sums, index + 1, target)) return true;
sums[i] -= nums[index];
} return false;
}
}

Updates on 12/19/2016 Thanks @benjamin19890721 for pointing out a very good optimization: Sorting the input array DESC will make the DFS process run much faster. Reason behind this is we always try to put the next matchstick in the first subset. If there is no solution, trying a longer matchstick first will get to negative conclusion earlier. Following is the updated code. Runtime is improved from more than 1000ms to around 40ms. A big improvement.

 public class Solution {
public boolean makesquare(int[] nums) {
if (nums==null || nums.length<4) return false;
int sideLen = 0;
for (int num : nums) {
sideLen += num;
}
if (sideLen % 4 != 0) return false;
sideLen /= 4;
Arrays.sort(nums);
reverse(nums);
return find(nums, new int[4], 0, sideLen);
} public boolean find(int[] nums, int[] edges, int index, int sideLen) {
if (index == nums.length) {
if (edges[0]==sideLen && edges[1]==sideLen && edges[2]==sideLen)
return true;
else return false;
} for (int i=0; i<4; i++) {
if (edges[i]+nums[index] > sideLen) continue;
edges[i] += nums[index];
if (find(nums, edges, index+1, sideLen)) return true;
edges[i] -= nums[index];
}
return false;
} public void reverse(int[] nums) {
int l=0, r=nums.length-1;
while (l < r) {
int temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
l++;
r--;
}
}
}

Grammar: How to sort array in descending order: http://www.java67.com/2016/07/how-to-sort-array-in-descending-order-in-java.html

How to sort object array in descending order

First, let's see the example of sorting an object array into ascending order. Then we'll see how to sort a primitive array in descending order. In order to sort a reference type array e.g. String array, Integer array or Employee array, you need to pass the Array.sort() method a reverse Comparator.

Fortunately, you don't need to code it yourself, you can use Collections.reverseOrder(Comparator comp) to get a reverse order Comparator. Just pass your Comparator to this method and it will return the opposite order Comparator.

If you are using Comparator method to sort in natural order, you can also use the overloaded Collection.reverseOrder() method. It returns a Comparator which sorts in the opposite of natural order. In fact, this is the one you will be using most of the time.

Here is an example of sorting Integer array in descending order:

Integer[] cubes = new Integer[] { 8, 27, 64, 125, 256 };
Arrays.sort(cubes, Collections.reverseOrder());

How to sort primitive array in descending order

Now, let's see how to sort a primitive array e.g. int[], long[],  float[] or char[] in descending order. As I told, there are no Arrays.sort() method which can sort the array in the reverse order. Many programmers make mistake of calling the above Array.sort() method as follows:

int[] squares = { 4, 25, 9, 36, 49 };
Arrays.sort(squares, Collections.reverseOrder());

This is compile time error "The method sort(int[]) in the type Arrays is not applicable for the arguments (int[], Comparator<Object>)" because there is no such method in the java.util.Arrays class.

The only way to sort a primitive array in descending order is first to sort it in ascending order and then reverse the array in place as shown here. Since in place reversal is an efficient algorithm and doesn't require extra memory, you can use it sort and reverse large array as well. You can also see a good book on data structure and algorithm e.g. Introduction to Algorithms to learn more about efficient sorting algorithm e.g. O(n) sorting algorithm like Bucket sort.

最新文章

  1. CSS 两列布局 之 左侧适应,右侧固定 3种方式
  2. The different of mouseover and mouseenter
  3. Linux Shell 从入门到删除根目录跑路指南
  4. VC亲自教你写BP
  5. 安卓微POS-PDA手持终端,支持离线在线联网销售开单;移动开单 盘点 功能
  6. 微信诡异的 40029 不合法的oauth_code
  7. curl命令学习(转载的)
  8. 读书笔记 effctive c++ Item 20 优先使用按const-引用传递(by-reference-to-const)而不是按值传递(by value)
  9. mbatis_逆向工程
  10. C++模板总结
  11. GMA Round 1 波动函数
  12. 简单的linux使用命令
  13. AspNetCore OpenId
  14. Java精品文章收藏
  15. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第4章编程练习9
  16. DATASNAP远程方法返回TSTREAM正解(转咏南兄)
  17. 用Navicat for MySQL 连接 CentOS 6.5
  18. 11.字符串{a,b}的幂集[回溯递归]
  19. composer如何自动验证并获取gitlab的私有库?
  20. (转).NET技术大系概览 (迄今为止最全的.NET技术栈)

热门文章

  1. 2015ACM/ICPC亚洲区长春站
  2. js直接打印pdf文件内容
  3. android Context 持有导致的内存泄漏
  4. ZooKeeper个人笔记Session管理
  5. PHP-Redis扩展使用手册(一)
  6. uva10986 堆优化单源最短路径(pas)
  7. 【BZOJ】3832: [Poi2014]Rally
  8. 不注册Activex 直接调用它
  9. HDU 3743 Frosh Week (线段树+离散化)
  10. AFNetworking3.1.0检查网络状态