|  |  |  | @ -0,0 +1,148 @@ | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.List; | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.Random; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 负责生成并添加括号 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | public class BracketManager { | 
			
		
	
		
			
				
					|  |  |  |  |   private static final Random RANDOM = new Random(); | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   /** | 
			
		
	
		
			
				
					|  |  |  |  |    * 根据元素个数选择括号对数 | 
			
		
	
		
			
				
					|  |  |  |  |    * 3 -> 80% 1对 20%0对 | 
			
		
	
		
			
				
					|  |  |  |  |    * 4 -> 90% 1对 10%2对 | 
			
		
	
		
			
				
					|  |  |  |  |    * 5 -> 50% 1对 50%2对 | 
			
		
	
		
			
				
					|  |  |  |  |    */ | 
			
		
	
		
			
				
					|  |  |  |  |   public int decideParenthesesPairs(int numCount) { | 
			
		
	
		
			
				
					|  |  |  |  |     return switch (numCount) { | 
			
		
	
		
			
				
					|  |  |  |  |       case 3 -> RANDOM.nextDouble() < 0.8 ? 1 : 0; | 
			
		
	
		
			
				
					|  |  |  |  |       case 4 -> RANDOM.nextDouble() < 0.9 ? 1 : 2; | 
			
		
	
		
			
				
					|  |  |  |  |       case 5 -> RANDOM.nextDouble() < 0.5 ? 1 : 2; | 
			
		
	
		
			
				
					|  |  |  |  |       default -> 0; | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   // 添加括号
 | 
			
		
	
		
			
				
					|  |  |  |  |   public String addParentheses(String expression, int pairs, List<Integer> numPositions) { | 
			
		
	
		
			
				
					|  |  |  |  |     String[] tokens = expression.split(" "); | 
			
		
	
		
			
				
					|  |  |  |  |     int numCount = numPositions.size(); | 
			
		
	
		
			
				
					|  |  |  |  |     boolean[] markLeft = new boolean[numCount]; | 
			
		
	
		
			
				
					|  |  |  |  |     boolean[] markRight = new boolean[numCount]; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     generateBracketPositions(numCount, numPositions, pairs, tokens, markLeft, markRight); | 
			
		
	
		
			
				
					|  |  |  |  |     String result = insertBrackets(tokens, markLeft, markRight); | 
			
		
	
		
			
				
					|  |  |  |  |     return validateParentheses(result) ? result : expression; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //计算生成括号的位置
 | 
			
		
	
		
			
				
					|  |  |  |  |   private void generateBracketPositions(int numCount, List<Integer> numPositions, int pairs, String[] tokens, | 
			
		
	
		
			
				
					|  |  |  |  |                                         boolean[] markLeft, boolean[] markRight) { | 
			
		
	
		
			
				
					|  |  |  |  |     int attempts = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     for (int p = 0; p < pairs && attempts < 50; p++, attempts++) { | 
			
		
	
		
			
				
					|  |  |  |  |       boolean placed = false; | 
			
		
	
		
			
				
					|  |  |  |  |       for (int tries = 0; tries < 50 && !placed; tries++) { | 
			
		
	
		
			
				
					|  |  |  |  |         int start = RANDOM.nextInt(numCount - 1); | 
			
		
	
		
			
				
					|  |  |  |  |         int end = start + 1 + RANDOM.nextInt(numCount - start - 1); | 
			
		
	
		
			
				
					|  |  |  |  |         if (end >= numCount) end = numCount - 1; | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |         // 20%概率尝试嵌套在已有括号内部
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (RANDOM.nextDouble() < 0.2) { | 
			
		
	
		
			
				
					|  |  |  |  |           for (int i = 0; i < numCount; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |             if (markLeft[i]) { | 
			
		
	
		
			
				
					|  |  |  |  |               start = i; | 
			
		
	
		
			
				
					|  |  |  |  |               end = i + RANDOM.nextInt(numCount - i); | 
			
		
	
		
			
				
					|  |  |  |  |               break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |          | 
			
		
	
		
			
				
					|  |  |  |  |         if (canPlaceBracket(start, end, markLeft, markRight, numPositions, tokens)) { | 
			
		
	
		
			
				
					|  |  |  |  |           markLeft[start] = true; | 
			
		
	
		
			
				
					|  |  |  |  |           markRight[end] = true; | 
			
		
	
		
			
				
					|  |  |  |  |           placed = true; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //检测添加括号的合法性
 | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean canPlaceBracket(int start, int end, boolean[] markLeft, boolean[] markRight, | 
			
		
	
		
			
				
					|  |  |  |  |                                   List<Integer> numPositions, String[] tokens) { | 
			
		
	
		
			
				
					|  |  |  |  |     if (isOuterMostBracket(start, end, markLeft.length)) return false; | 
			
		
	
		
			
				
					|  |  |  |  |     if (isInvalidOverlap(start, end, markLeft, markRight)) return false; | 
			
		
	
		
			
				
					|  |  |  |  |     return isValidBracketRange(tokens, numPositions, start, end); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //避免最外层括号
 | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean isOuterMostBracket(int start, int end, int numCount) { | 
			
		
	
		
			
				
					|  |  |  |  |     return start == 0 && end == numCount - 1; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //允许嵌套但禁止交叉
 | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean isInvalidOverlap(int start, int end, boolean[] markLeft, boolean[] markRight) { | 
			
		
	
		
			
				
					|  |  |  |  |     for (int i = start; i <= end; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |       // start/end可重合,内部禁止已有左右括号
 | 
			
		
	
		
			
				
					|  |  |  |  |       if ((i != start && markLeft[i]) || (i != end && markRight[i])) return true; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     return false; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //检测括号是否有意义(优先级)
 | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean isValidBracketRange(String[] tokens, List<Integer> numPositions, int start, int end) { | 
			
		
	
		
			
				
					|  |  |  |  |     int opStart = numPositions.get(start) + 1; | 
			
		
	
		
			
				
					|  |  |  |  |     int opEnd = numPositions.get(end) - 1; | 
			
		
	
		
			
				
					|  |  |  |  |     String firstOp = null; | 
			
		
	
		
			
				
					|  |  |  |  |     boolean hasHigherOuterOp = false; | 
			
		
	
		
			
				
					|  |  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |  |     for (int i = opStart; i <= opEnd; i += 2) { | 
			
		
	
		
			
				
					|  |  |  |  |       if (!isNumber(tokens[i])) { | 
			
		
	
		
			
				
					|  |  |  |  |         if (firstOp == null) firstOp = tokens[i]; | 
			
		
	
		
			
				
					|  |  |  |  |         else if (isDifferentPriority(firstOp, tokens[i])) { | 
			
		
	
		
			
				
					|  |  |  |  |           hasHigherOuterOp = true; | 
			
		
	
		
			
				
					|  |  |  |  |           break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     return hasHigherOuterOp || firstOp == null; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //比较运算符优先级
 | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean isDifferentPriority(String op1, String op2) { | 
			
		
	
		
			
				
					|  |  |  |  |     int p1 = (op1.equals("+") || op1.equals("-")) ? 1 : 2; | 
			
		
	
		
			
				
					|  |  |  |  |     int p2 = (op2.equals("+") || op2.equals("-")) ? 1 : 2; | 
			
		
	
		
			
				
					|  |  |  |  |     return p1 != p2; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //插入操作
 | 
			
		
	
		
			
				
					|  |  |  |  |   private String insertBrackets(String[] tokens, boolean[] markLeft, boolean[] markRight) { | 
			
		
	
		
			
				
					|  |  |  |  |     StringBuilder sb = new StringBuilder(); | 
			
		
	
		
			
				
					|  |  |  |  |     int numIndex = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     for (String token : tokens) { | 
			
		
	
		
			
				
					|  |  |  |  |       if (isNumber(token)) { | 
			
		
	
		
			
				
					|  |  |  |  |         if (markLeft[numIndex]) sb.append("( "); | 
			
		
	
		
			
				
					|  |  |  |  |         sb.append(token); | 
			
		
	
		
			
				
					|  |  |  |  |         if (markRight[numIndex]) sb.append(" )"); | 
			
		
	
		
			
				
					|  |  |  |  |         numIndex++; | 
			
		
	
		
			
				
					|  |  |  |  |       } else { | 
			
		
	
		
			
				
					|  |  |  |  |         sb.append(" ").append(token).append(" "); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     return sb.toString(); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   //检查括号是否缺失
 | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean validateParentheses(String expr) { | 
			
		
	
		
			
				
					|  |  |  |  |     int balance = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     for (char c : expr.toCharArray()) { | 
			
		
	
		
			
				
					|  |  |  |  |       if (c == '(') balance++; | 
			
		
	
		
			
				
					|  |  |  |  |       if (c == ')') balance--; | 
			
		
	
		
			
				
					|  |  |  |  |       if (balance < 0) return false; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     return balance == 0; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |    | 
			
		
	
		
			
				
					|  |  |  |  |   private boolean isNumber(String token) { | 
			
		
	
		
			
				
					|  |  |  |  |     try { Integer.parseInt(token); return true; } | 
			
		
	
		
			
				
					|  |  |  |  |     catch (NumberFormatException e) { return false; } | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } |